/downloader/lib/Mage/Connect/Package.php
PHP | 1499 lines | 1098 code | 66 blank | 335 comment | 64 complexity | c301c73d327c386776c196390021f7b5 MD5 | raw file
- <?php
- /**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magento.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magento.com for more information.
- *
- * @category Mage
- * @package Mage_Connect
- * @copyright Copyright (c) 2006-2016 X.commerce, Inc. and affiliates (http://www.magento.com)
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
- */
- /**
- * Class to work with Magento Connect packages
- *
- * @category Mage
- * @package Mage_Connect
- * @author Magento Core Team <core@magentocommerce.com>
- */
- class Mage_Connect_Package
- {
- const PACKAGE_XML_DIR = 'var/package';
- /**
- * Contain SimpleXMLElement for composing document.
- *
- * @var SimpleXMLElement
- */
- protected $_packageXml;
- /**
- * Internal cache
- *
- * @var array
- */
- protected $_authors;
- /**
- * Internal cache
- *
- * @var array
- */
- protected $_contents;
- /**
- * Internal cache
- *
- * @var array
- */
- protected $_hashContents;
- /**
- * Internal cache
- *
- * @var array
- */
- protected $_compatible;
- /**
- * Internal cache
- *
- * @var array
- */
- protected $_dependencyPhpExtensions;
- /**
- * Internal cache
- *
- * @var array
- */
- protected $_dependencyPackages;
- /**
- * A helper object that can read from a package archive
- *
- * @var Mage_Connect_Package_Reader
- */
- protected $_reader;
- /**
- * A helper object that can create and write to a package archive
- *
- * @var Mage_Connect_Package_Writer
- */
- protected $_writer;
- /**
- * Validator object
- *
- * @var Mage_Connect_Validator
- */
- protected $_validator = null;
- /**
- * Validation errors
- *
- * @var array
- */
- protected $_validationErrors = array();
- /**
- * Object with target
- *
- * @var Mage_Connect_Package_Target
- */
- protected $_target = null;
- /**
- * Config object
- *
- * @var Mage_Connect_Config
- */
- protected $_config = null;
- /**
- * Creates a package object (empty, or from existing archive, or from package definition xml)
- *
- * @param null|string|resource $source
- */
- public function __construct($source=null)
- {
- libxml_use_internal_errors(true);
- if (is_string($source)) {
- // check what's in the string (a package definition or a package filename)
- if (0 === strpos($source, "<?xml")) {
- // package definition xml
- $this->_init($source);
- } elseif (is_file($source) && is_readable($source)) {
- // package archive filename
- $this->_loadFile($source);
- } else {
- throw new Mage_Exception('Invalid package source');
- }
- } elseif (is_resource($source)) {
- $this->_loadResource($source);
- } elseif (is_null($source)) {
- $this->_init();
- } else {
- throw new Mage_Exception('Invalid package source');
- }
- }
- /**
- * Initializes an empty package object
- *
- * @param null|string $definition optional package definition xml
- * @return Mage_Connect_Package
- */
- protected function _init($definition=null)
- {
- if (!is_null($definition)) {
- $this->_packageXml = simplexml_load_string($definition);
- } else {
- $packageXmlStub = <<<END
- <?xml version="1.0"?>
- <package>
- <name />
- <version />
- <stability />
- <license />
- <channel />
- <extends />
- <summary />
- <description />
- <notes />
- <authors />
- <date />
- <time />
- <contents />
- <compatible />
- <dependencies />
- </package>
- END;
- $this->_packageXml = simplexml_load_string($packageXmlStub);
- }
- return $this;
- }
- /**
- * Loads a package from specified file
- *
- * @param string $filename
- * @return Mage_Connect_Package
- */
- protected function _loadFile($filename='')
- {
- if (is_null($this->_reader)) {
- $this->_reader = new Mage_Connect_Package_Reader($filename);
- }
- $content = $this->_reader->load();
- $this->_packageXml = simplexml_load_string($content);
- return $this;
- }
- /**
- * Creates a package and saves it
- *
- * @param string $path
- * @return Mage_Connect_Package
- */
- public function save($path)
- {
- $this->validate();
- $path = rtrim($path, "\\/") . DS;
- $this->_savePackage($path);
- return $this;
- }
- /**
- * Creates a package archive and saves it to specified path
- *
- * @param string $path
- * @return Mage_Connect_Package
- */
- protected function _savePackage($path)
- {
- $fileName = $this->getReleaseFilename();
- if (is_null($this->_writer)) {
- $this->_writer = new Mage_Connect_Package_Writer($this->getContents(), $path.$fileName);
- }
- $this->_writer
- ->composePackage()
- ->addPackageXml($this->getPackageXml())
- ->archivePackage();
- return $this;
- }
- /**
- * Retrieve Target object
- *
- * @return Mage_Connect_Package_Target
- */
- protected function getTarget()
- {
- if (!$this->_target instanceof Mage_Connect_Package_Target) {
- $this->_target = new Mage_Connect_Package_Target();
- }
- return $this->_target;
- }
- public function setTarget($arg)
- {
- if ($arg instanceof Mage_Connect_Package_Target) {
- $this->_target = $arg;
- }
- }
- /* Mutators */
- /**
- * Puts value to name
- *
- * @param string $name
- * @return Mage_Connect_Package
- */
- public function setName($name)
- {
- $this->_packageXml->name = $name;
- return $this;
- }
- /**
- * Puts value to <channel />
- *
- * @param string $channel
- * @return Mage_Connect_Package
- */
- public function setChannel($channel)
- {
- $this->_packageXml->channel = $channel;
- return $this;
- }
- /**
- * Puts value to <summary />
- *
- * @param string $summary
- * @return Mage_Connect_Package
- */
- public function setSummary($summary)
- {
- $this->_packageXml->summary = $summary;
- return $this;
- }
- /**
- * Puts value to <description />
- *
- * @param string $description
- * @return Mage_Connect_Package
- */
- public function setDescription($description)
- {
- $this->_packageXml->description = $description;
- return $this;
- }
- /**
- * Puts value to <authors />
- *
- * array(
- * array('name'=>'Name1', 'user'=>'User1', 'email'=>'email1@email.com'),
- * array('name'=>'Name2', 'user'=>'User2', 'email'=>'email2@email.com'),
- * );
- *
- * @param array $authors
- * @return Mage_Connect_Package
- */
- public function setAuthors($authors)
- {
- $this->_authors = $authors;
- foreach ($authors as $_author) {
- $this->addAuthor($_author['name'], $_author['user'], $_author['email']);
- }
- return $this;
- }
- /**
- * Add author to <authors/>
- *
- * @param string $name
- * @param string $user
- * @param string $email
- * @return Mage_Connect_Package
- */
- public function addAuthor($name=null, $user=null, $email=null)
- {
- $this->_authors[] = array(
- 'name' =>$name,
- 'user' =>$user,
- 'email'=>$email
- );
- $author = $this->_packageXml->authors->addChild('author');
- $author->addChild('name', $name);
- $author->addChild('user', $user);
- $author->addChild('email', $email);
- return $this;
- }
- /**
- * Puts value to <date/>. Format should be Y-M-D.
- *
- * @param string $date
- * @return Mage_Connect_Package
- */
- public function setDate($date)
- {
- $this->_packageXml->date = $date;
- return $this;
- }
- /**
- * Puts value to <time />. Format should be H:i:s.
- *
- * @param string $time
- * @return Mage_Connect_Package
- */
- public function setTime($time)
- {
- $this->_packageXml->time = $time;
- return $this;
- }
- /**
- * Puts value to <version/>. Format should be X.Y.Z.
- *
- * @param string $version
- * @return Mage_Connect_Package
- */
- public function setVersion($version)
- {
- $this->_packageXml->version = $version;
- return $this;
- }
- /**
- * Puts value to <stability/>. It can be alpha, beta, devel and stable.
- *
- * @param string $stability
- * @return Mage_Connect_Package
- */
- public function setStability($stability)
- {
- $this->_packageXml->stability = $stability;
- return $this;
- }
- /**
- * Puts value to <license/>, also method can used for set attribute URI.
- *
- * @param string $license
- * @param string $uri
- * @return Mage_Connect_Package
- */
- public function setLicense($license, $uri=null)
- {
- $this->_packageXml->license = $license;
- if ($uri) {
- $this->_packageXml->license['uri'] = $uri;
- }
- return $this;
- }
- /**
- * Puts value to <notes/>.
- *
- * @param string $notes
- * @return Mage_Connect_Package
- */
- public function setNotes($notes)
- {
- $this->_packageXml->notes = $notes;
- return $this;
- }
- /**
- * Retrieve SimpleXMLElement node by xpath. If it absent, create new.
- * For comparing nodes method uses attribute "name" in each nodes.
- * If attribute "name" is same for both nodes, nodes are same.
- *
- * @param string $tag
- * @param SimpleXMLElement $parent
- * @param string $name
- * @return SimpleXMLElement
- */
- protected function _getNode($tag, $parent, $name='')
- {
- $found = false;
- foreach ($parent->xpath($tag) as $_node) {
- if ($_node['name'] == $name) {
- $node = $_node;
- $found = true;
- break;
- }
- }
- if (!$found) {
- $node = $parent->addChild($tag);
- if ($name) {
- $node->addAttribute('name', $name);
- }
- }
- return $node;
- }
- /**
- * Add directory or file to <contents />.
- *
- * @param string $path Path to directory or file
- * @param string $targetName Target name.
- * @param string $hash MD5 hash of the file
- * @return Mage_Connect_Package
- */
- public function addContent($path, $targetName)
- {
- $found = false;
- $parent = $this->_getNode('target', $this->_packageXml->contents, $targetName);
- $source = str_replace('\\', '/', $path);
- $directories = explode('/', dirname($source));
- foreach ($directories as $directory) {
- $parent = $this->_getNode('dir', $parent, $directory);
- }
- $fileName = basename($source);
- if ($fileName!='') {
- $fileNode = $parent->addChild('file');
- $fileNode->addAttribute('name', $fileName);
- $targetDir = $this->getTarget()->getTargetUri($targetName);
- $hash = md5_file($targetDir.DS.$path);
- $fileNode->addAttribute('hash', $hash);
- }
- return $this;
- }
- /**
- * Add directory recursively (with subdirectory and file).
- * Exclude and Include can be add using Regular Expression.
- *
- * @param string $targetName Target name
- * @param string $targetDir Path for target name
- * @param string $path Path to directory
- * @param string $exclude Exclude
- * @param string $include Include
- * @return Mage_Connect_Package
- */
- public function addContentDir($targetName, $path, $exclude=null, $include=null)
- {
- $targetDir = $this->getTarget()->getTargetUri($targetName);
- $targetDirLen = strlen($targetDir . DS);
- //get all subdirectories and files.
- $entries = @glob($targetDir. DS . $path . DS . "{,.}*", GLOB_BRACE);
- if (!empty($entries)) {
- foreach ($entries as $entry) {
- $filePath = substr($entry, $targetDirLen);
- if (!empty($include) && !preg_match($include, $filePath)) {
- continue;
- }
- if (!empty($exclude) && preg_match($exclude, $filePath)) {
- continue;
- }
- if (is_dir($entry)) {
- $baseName = basename($entry);
- if ('.'===$baseName || '..'===$baseName) {
- continue;
- }
- //for subdirectory call method recursively
- $this->addContentDir($targetName, $filePath, $exclude, $include);
- } elseif (is_file($entry)) {
- $this->addContent($filePath, $targetName);
- }
- }
- }
- return $this;
- }
- /**
- * Add value to <compatible />.
- *
- * @param string $packageName
- * @param string $channel
- * @param string $minVersion
- * @param string $maxVersion
- * @return Mage_Connect_Package
- */
- public function addCompatible($packageName, $channel, $minVersion, $maxVersion)
- {
- $package = $this->_packageXml->compatible->addChild('package');
- $package->addChild('name', $packageName);
- $package->addChild('channel', $channel);
- $package->addChild('min', $minVersion);
- $package->addChild('max', $maxVersion);
- return $this;
- }
- /**
- * Set dependency from php version.
- *
- * @param string $minVersion
- * @param string $maxVersion
- * @return Mage_Connect_Package
- */
- public function setDependencyPhpVersion($minVersion, $maxVersion)
- {
- $parent = $this->_packageXml->dependencies;
- $parent = $this->_getNode('required', $parent);
- $parent = $this->_getNode('php', $parent);
- $parent->addChild('min', $minVersion);
- $parent->addChild('max', $maxVersion);
- return $this;
- }
- /**
- * Check PHP version restriction
- * @param $phpVersion PHP_VERSION by default
- * @return true | string
- */
- public function checkPhpVersion()
- {
- $min = $this->getDependencyPhpVersionMin();
- $max = $this->getDependencyPhpVersionMax();
- $minOk = $min? version_compare(PHP_VERSION, $min, ">=") : true;
- $maxOk = $max? version_compare(PHP_VERSION, $max, "<=") : true;
- if(!$minOk || !$maxOk) {
- $err = "requires PHP version ";
- if($min && $max) {
- $err .= " >= $min and <= $max ";
- } elseif($min) {
- $err .= " >= $min ";
- } elseif($max) {
- $err .= " <= $max ";
- }
- $err .= " current is: ".PHP_VERSION;
- return $err;
- }
- return true;
- }
- /**
- * Check PHP extensions availability
- * @throws Exceptiom on failure
- * @return true | array
- */
- public function checkPhpDependencies()
- {
- $errors = array();
- foreach($this->getDependencyPhpExtensions() as $dep)
- {
- if(!extension_loaded($dep['name'])) {
- $errors[] = $dep;
- }
- }
- if(count($errors)) {
- return $errors;
- }
- return true;
- }
- /**
- * Set dependency from php extensions.
- *
- * $extension has next view:
- * array('curl', 'mysql')
- *
- * @param array|string $extensions
- * @return Mage_Connect_Package
- */
- public function setDependencyPhpExtensions($extensions)
- {
- foreach($extensions as $_extension) {
- $this->addDependencyExtension(
- $_extension['name'],
- $_extension['min_version'],
- $_extension['max_version']
- );
- }
- return $this;
- }
- /**
- * Set dependency from another packages.
- *
- * $packages should contain:
- * array(
- * array('name'=>'test1', 'channel'=>'test1', 'min_version'=>'0.0.1', 'max_version'=>'0.1.0'),
- * array('name'=>'test2', 'channel'=>'test2', 'min_version'=>'0.0.1', 'max_version'=>'0.1.0'),
- * )
- *
- * @param array $packages
- * @param bool $clear
- * @return Mage_Connect_Package
- */
- public function setDependencyPackages($packages, $clear = false)
- {
- if($clear) {
- unset($this->_packageXml->dependencies->required->package);
- }
- foreach($packages as $_package) {
- $filesArrayCondition = isset($_package['files']) && is_array($_package['files']);
- $filesArray = $filesArrayCondition ? $_package['files'] : array();
- $this->addDependencyPackage(
- $_package['name'],
- $_package['channel'],
- $_package['min_version'],
- $_package['max_version'],
- $filesArray
- );
- }
- return $this;
- }
- /**
- * Add package to dependency packages.
- *
- * @param string $package
- * @param string $channel
- * @param string $minVersion
- * @param string $maxVersion
- * @return Mage_Connect_Package
- */
- public function addDependencyPackage($name, $channel, $minVersion, $maxVersion, $files = array())
- {
- $parent = $this->_packageXml->dependencies;
- $parent = $this->_getNode('required', $parent);
- $parent = $parent->addChild('package');
- $parent->addChild('name', $name);
- $parent->addChild('channel', $channel);
- $parent->addChild('min', $minVersion);
- $parent->addChild('max', $maxVersion);
- if(count($files)) {
- $parent = $parent->addChild('files');
- foreach($files as $row) {
- if(!empty($row['target']) && !empty($row['path'])) {
- $node = $parent->addChild("file");
- $node["target"] = $row['target'];
- $node["path"] = $row['path'];
- }
- }
- }
- return $this;
- }
- /**
- * Add package to dependency extension.
- *
- * @param string $package
- * @param string $minVersion
- * @param string $maxVersion
- * @return Mage_Connect_Package
- */
- public function addDependencyExtension($name, $minVersion, $maxVersion)
- {
- $parent = $this->_packageXml->dependencies;
- $parent = $this->_getNode('required', $parent);
- $parent = $parent->addChild('extension');
- $parent->addChild('name', $name);
- $parent->addChild('min', $minVersion);
- $parent->addChild('max', $maxVersion);
- return $this;
- }
- /* Accessors */
- /**
- * Getter
- *
- * @return string
- */
- public function getName()
- {
- return (string)$this->_packageXml->name;
- }
- /**
- * Getter
- *
- * @return string
- */
- public function getChannel()
- {
- return (string)$this->_packageXml->channel;
- }
- /**
- * Getter
- *
- * @return string
- */
- public function getSummary()
- {
- return (string)$this->_packageXml->summary;
- }
- /**
- * Getter
- *
- * @return string
- */
- public function getDescription()
- {
- return (string)$this->_packageXml->description;
- }
- /**
- * Get list of authors in associative array.
- *
- * @return array
- */
- public function getAuthors()
- {
- if (is_array($this->_authors)) return $this->_authors;
- $this->_authors = array();
- if(!isset($this->_packageXml->authors->author)) {
- return array();
- }
- foreach ($this->_packageXml->authors->author as $_author) {
- $this->_authors[] = array(
- 'name' => (string)$_author->name,
- 'user' => (string)$_author->user,
- 'email'=> (string)$_author->email
- );
- }
- return $this->_authors;
- }
- /**
- * Getter
- *
- * @return string
- */
- public function getDate()
- {
- return (string)$this->_packageXml->date;
- }
- /**
- * Getter
- *
- * @return string
- */
- public function getTime()
- {
- return (string)$this->_packageXml->time;
- }
- /**
- * Getter
- *
- * @return string
- */
- public function getVersion()
- {
- return (string)$this->_packageXml->version;
- }
- /**
- * Getter
- *
- * @return string
- */
- public function getStability()
- {
- return (string)$this->_packageXml->stability;
- }
- /**
- * Getter
- *
- * @return string
- */
- public function getLicense()
- {
- return (string)$this->_packageXml->license;
- }
- /**
- * Getter
- *
- * @return string
- */
- public function getLicenseUri()
- {
- return (string)$this->_packageXml->license['uri'];
- }
- /**
- * Getter
- *
- * @return string
- */
- public function getNotes()
- {
- return (string)$this->_packageXml->notes;
- }
- /**
- * Create list of all files from package.xml
- *
- * @return array
- */
- public function getContents()
- {
- if (is_array($this->_contents)) return $this->_contents;
- $this->_contents = array();
- if(!isset($this->_packageXml->contents->target)) {
- return $this->_contents;
- }
- foreach($this->_packageXml->contents->target as $target) {
- $targetUri = $this->getTarget()->getTargetUri($target['name']);
- $this->_getList($target, $targetUri);
- }
- return $this->_contents;
- }
- /**
- * Helper for getContents(). Create recursively list.
- *
- * @param SimpleXMLElement $parent
- * @param string $path
- */
- protected function _getList($parent, $path)
- {
- if (count($parent) == 0) {
- $this->_contents[] = $path;
- } else {
- foreach($parent as $_content) {
- $this->_getList($_content, ($path ? $path . DS : '') . $_content['name']);
- }
- }
- }
- /**
- * Create list of all files from package.xml with hash
- *
- * @return array
- */
- public function getHashContents()
- {
- if (is_array($this->_hashContents)) return $this->_hashContents;
- $this->_hashContents = array();
- if(!isset($this->_packageXml->contents->target)) {
- return $this->_hashContents;
- }
- foreach($this->_packageXml->contents->target as $target) {
- $targetUri = $this->getTarget()->getTargetUri($target['name']);
- $this->_getHashList($target, $targetUri);
- }
- return $this->_hashContents;
- }
- /**
- * Helper for getHashContents(). Create recursively list.
- *
- * @param SimpleXMLElement $parent
- * @param string $path
- */
- protected function _getHashList($parent, $path, $hash='')
- {
- if (count($parent) == 0) {
- $this->_hashContents[$path] = $hash;
- } else {
- foreach($parent as $_content) {
- $contentHash = '';
- if (isset($_content['hash'])) {
- $contentHash = (string)$_content['hash'];
- }
- $this->_getHashList($_content, ($path ? $path . DS : '') . $_content['name'], $contentHash);
- }
- }
- }
- /**
- * Get compatible packages.
- *
- * @return array
- */
- public function getCompatible()
- {
- if (is_array($this->_compatible)) return $this->_compatible;
- $this->_compatible = array();
- if(!isset($this->_packageXml->compatible->package)) {
- return array();
- }
- foreach ($this->_packageXml->compatible->package as $_package) {
- $this->_compatible[] = array(
- 'name' => (string)$_package->name,
- 'channel' => (string)$_package->channel,
- 'min' => (string)$_package->min,
- 'max' => (string)$_package->max
- );
- }
- return $this->_compatible;
- }
- /**
- * Getter
- *
- * @return string
- */
- public function getDependencyPhpVersionMin()
- {
- if(!isset($this->_packageXml->dependencies->required->php->min)) {
- return false;
- }
- return (string)$this->_packageXml->dependencies->required->php->min;
- }
- /**
- * Getter
- *
- * @return string
- */
- public function getDependencyPhpVersionMax()
- {
- if(!isset($this->_packageXml->dependencies->required->php->max)) {
- return false;
- }
- return (string)$this->_packageXml->dependencies->required->php->max;
- }
- /**
- * Get list of php extensions.
- *
- * @return array
- */
- public function getDependencyPhpExtensions()
- {
- if (is_array($this->_dependencyPhpExtensions)) return $this->_dependencyPhpExtensions;
- $this->_dependencyPhpExtensions = array();
- if (!isset($this->_packageXml->dependencies->required->extension)) {
- return $this->_dependencyPhpExtensions;
- }
- foreach($this->_packageXml->dependencies->required->extension as $_package) {
- $this->_dependencyPhpExtensions[] = array(
- 'name' => (string)$_package->name,
- 'min' => (string)$_package->min,
- 'max' => (string)$_package->max,
- );
- }
- return $this->_dependencyPhpExtensions;
- }
- /**
- * Get list of dependency packages.
- *
- * @return array
- */
- public function getDependencyPackages()
- {
- $this->_dependencyPackages = array();
- if (!isset($this->_packageXml->dependencies->required->package)) {
- return $this->_dependencyPackages;
- }
- foreach($this->_packageXml->dependencies->required->package as $_package) {
- $add = array(
- 'name' => (string)$_package->name,
- 'channel' => (string)$_package->channel,
- 'min' => (string)$_package->min,
- 'max' => (string)$_package->max,
- );
- if(isset($_package->files)) {
- $add['files'] = array();
- foreach($_package->files as $node) {
- if(isset($node->file)) {
- $add['files'][] = array('target' => (string) $node->file['target'], 'path'=> (string) $node->file['path']);
- }
- }
- }
- $this->_dependencyPackages[] = $add;
- }
- return $this->_dependencyPackages;
- }
- /**
- * Get string with XML content.
- *
- * @return string
- */
- public function getPackageXml()
- {
- return $this->_packageXml->asXml();
- }
- /**
- * Validator instance (single)
- *
- * @return Mage_Connect_Validator
- */
- protected function validator()
- {
- if(is_null($this->_validator)) {
- $this->_validator = new Mage_Connect_Validator();
- }
- return $this->_validator;
- }
- /**
- * Get validation error strings
- *
- * @return array
- */
- public function getErrors()
- {
- return $this->_validationErrors;
- }
- /**
- * Setter for validation errors
- *
- * @param array $errors
- * @return
- */
- protected function setErrors(array $errors)
- {
- $this->_validationErrors = $errors;
- }
- /**
- * Check validation result.
- * Returns true if package data is invalid.
- *
- * @return bool
- */
- public function hasErrors()
- {
- return count($this->_validationErrors) != 0;
- }
- /**
- * Validate package. Errors can be
- * retreived by calling getErrors();
- *
- * @return bool
- */
- public function validate()
- {
- $v = $this->validator();
- /**
- * Validation map
- *
- * Format:
- *
- * 'key' => array(
- * 'method' => this class method name to call, string, required
- * 'method_args' => optional args for 'method' call, array, optional
- * 'v_method' => validator method to call, string, required
- * 'error' => custom error string when validation fails, optional
- * if not set, error string fprmatted as "Invalid '$key' specified"
- * 'v_error_method' => validator method - when called returned error string
- * prepared by validator, optional,
- * if not set => see 'error'
- * 'optional' => optional value, if it's empty validation result ignored
- *
- */
- $validateMap = array(
- 'name' => array('method' => 'getName',
- 'v_method' => 'validatePackageName',
- 'error'=>"Invalid package name, allowed: [a-zA-Z0-9_-] chars"),
- 'version' => array('method' => 'getVersion',
- 'v_method' => 'validateVersion',
- 'error'=>"Invalid version, should be like: x.x.x"),
- 'stability' => array('method' => 'getStability',
- 'v_method' => 'validateStability',
- 'error'=>"Invalid stability"),
- 'date' => array('method' => 'getDate',
- 'v_method' => 'validateDate',
- 'error'=>"Invalid date, should be YYYY-DD-MM"),
- 'license_uri' => array('method' => 'getLicenseUri',
- 'v_method' => 'validateLicenseUrl',
- 'error'=>"Invalid license URL"),
- 'channel' => array('method' => 'getChannel',
- 'v_method' => 'validateChannelNameOrUri',
- 'error'=>"Invalid channel URL"),
- 'authors' => array('method' => 'getAuthors',
- 'v_method' => 'validateAuthors',
- 'v_error_method' => 'getErrors'),
- 'php_min' => array('method' => 'getDependencyPhpVersionMin',
- 'v_method' => 'validateVersion',
- 'error' => 'PHP minimum version invalid',
- 'optional' => true ),
- 'php_max' => array('method' => 'getDependencyPhpVersionMax',
- 'v_method' => 'validateVersion',
- 'error' => 'PHP maximum version invalid',
- 'optional' => true ),
- 'compatible' => array('method' => 'getCompatible',
- 'v_method' => 'validateCompatible',
- 'v_error_method' => 'getErrors'),
- 'content' => array('method' => 'getContents',
- 'v_method' => 'validateContents',
- 'v_args' => array('config' => $this->getConfig()),
- 'v_error_method' => 'getErrors'),
- );
- $errors = array();
- /**
- * Iterate validation map
- */
- foreach($validateMap as $name=>$data) {
- /**
- * Check mandatory rules fields
- */
- if(!isset($data['method'], $data['v_method'])) {
- throw new Mage_Exception("Invalid rules specified!");
- }
- $method = $data['method'];
- $validatorMethod = $data['v_method'];
- /**
- * If $optional === false, value is mandatory
- */
- $optional = isset($data['optional']) ? (bool) $data['optional'] : false;
- /**
- * Check for method availability, package
- */
- if(!method_exists($this, $method)) {
- throw new Mage_Exception("Invalid method specified for Package : $method");
- }
- /**
- * Check for method availability, validator
- */
- if(!method_exists($v, $validatorMethod)) {
- throw new Mage_Exception("Invalid method specified for Validator : $validatorMethod");
- }
- /**
- * If $data['error'] => get error string from $data['error']
- * Else concatenate "Invalid '{$name}' specified"
- */
- $errorString = isset($data['error']) ? $data['error'] : "Invalid '{$name}' specified";
- /**
- * Additional method args check
- * array() by default
- */
- $methodArgs = isset($data['method_args']) ? $data['method_args'] : array();
- /**
- * Call package method
- */
- $out = @call_user_func_array(array($this, $method), $methodArgs);
- /**
- * Skip if result is empty and value is optional
- */
- if(empty($out) && $optional) {
- continue;
- }
- /**
- * Additional validator arguments, merged with array($out)
- */
- $validatorArgs = isset($data['v_args']) ? array_merge(array($out), $data['v_args']) : array($out);
- /**
- * Get validation result
- */
- $result = call_user_func_array(array($v, $validatorMethod), $validatorArgs);
- /**
- * Skip if validation success
- */
- if($result) {
- continue;
- }
- /**
- * From where to get error string?
- * If validator callback method specified, call it to get errors array
- * Else get it from $errorString - local error string
- */
- $validatorFetchErrorsMethod = isset($data['v_error_method']) ? $data['v_error_method'] : false;
- if (false !== $validatorFetchErrorsMethod) {
- $errorString = call_user_func_array(array($v, $validatorFetchErrorsMethod), array());
- }
- /**
- * If errors is array => merge
- * Else append
- */
- if(is_array($errorString)) {
- $errors = array_merge($errors, $errorString);
- } else {
- $errors[] = $errorString;
- }
- }
- /**
- * Set local errors
- */
- $this->setErrors($errors);
- /**
- * Return true if there's no errors :)
- */
- return ! $this->hasErrors();
- }
- /**
- * Return package release filename w/o extension
- * @return string
- */
- public function getReleaseFilename()
- {
- return $this->getName()."-".$this->getVersion();
- }
- /**
- * Return release filepath w/o extension
- * @return string
- */
- public function getRelaseDirFilename()
- {
- return $this->getName() . DS . $this->getVersion() . DS . $this->getReleaseFilename();
- }
- /**
- * Clear dependencies
- *
- * @return Mage_Connect_Package
- */
- public function clearDependencies()
- {
- $this->_packageXml->dependencies = null;
- return $this;
- }
- /**
- * Clear contents
- *
- * @return Mage_Connect_Package
- */
- public function clearContents()
- {
- $this->_packageXml->contents = null;
- return $this;
- }
- /**
- * Get config
- *
- * @return Mage_Connect_Config
- */
- public function getConfig()
- {
- return $this->_config;
- }
- /**
- * Set config
- *
- * @param Mage_Connect_Config $config
- */
- public function setConfig($config)
- {
- $this->_config = $config;
- }
- /**
- * Import package information from previous version of Magento Connect Manager
- *
- * @param array $data
- *
- * @return Mage_Connect_Package
- */
- public function importDataV1x(array $data)
- {
- $this->_packageXml = null;
- $this->_init();
- // Import simple data
- if (isset($data['name'])) {
- $this->setName($data['name']);
- }
- if (isset($data['summary'])) {
- $this->setSummary($data['summary']);
- }
- if (isset($data['description'])) {
- $this->setDescription($data['description']);
- }
- if (isset($data['channel'])) {
- $this->setChannel($this->convertChannelFromV1x($data['channel']));
- }
- if (isset($data['license'])) {
- if (is_array($data['license'])) {
- $this->setLicense($data['license']['_content'], $data['license']['attribs']['uri']);
- } else {
- $this->setLicense($data['license']);
- }
- }
- if (isset($data['version'])) {
- $this->setVersion($data['version']['release']);
- }
- if (isset($data['stability'])) {
- $this->setStability($data['stability']['release']);
- }
- if (isset($data['notes'])) {
- $this->setNotes($data['notes']);
- }
- if (isset($data['date'])) {
- $this->setDate($data['date']);
- }
- if (isset($data['time'])) {
- $this->setTime($data['time']);
- }
- // Import authors
- $authors = array();
- $authorRoles = array('lead', 'developer', 'contributor', 'helper');
- foreach ($authorRoles as $authorRole) {
- if (isset($data[$authorRole])) {
- $authorList = $data[$authorRole];
- if (!is_array($authorList) || isset($authorList['name'])) {
- $authorList = array($authorList);
- }
- foreach ($authorList as $authorRawData) {
- $author = array();
- $author['name'] = $authorRawData['name'];
- $author['user'] = $authorRawData['user'];
- $author['email'] = $authorRawData['email'];
- array_push($authors, $author);
- }
- }
- }
- $this->setAuthors($authors);
- // Import dependencies
- $packages = array();
- $extensions = array();
- if (isset($data['dependencies']) && is_array($data['dependencies'])) {
- $dependencySections = array('required', 'optional');
- $elementTypes = array('package', 'extension');
- foreach ($dependencySections as $dependencySection) {
- if (isset($data['dependencies'][$dependencySection])) {
- // Handle required PHP version
- if ($dependencySection == 'required' && isset($data['dependencies']['required']['php'])) {
- $this->setDependencyPhpVersion($data['dependencies']['required']['php']['min'], $data['dependencies']['required']['php']['max']);
- }
- // Handle extensions
- if (isset($data['dependencies'][$dependencySection]['extension'])) {
- $extensionList = $data['dependencies'][$dependencySection]['extension'];
- if (!is_array($extensionList) || isset($extensionList['name'])) {
- $extensionList = array($extensionList);
- }
- foreach ($extensionList as $extensionRawData) {
- $extension = array();
- $extension['name'] = $extensionRawData['name'];
- $extension['min_version'] = isset($extensionRawData['min']) ? $extensionRawData['min'] : null;
- $extension['max_version'] = isset($extensionRawData['max']) ? $extensionRawData['max'] : null;
- array_push($extensions, $extension);
- }
- }
- // Handle packages
- if (isset($data['dependencies'][$dependencySection]['package'])) {
- $packageList = $data['dependencies'][$dependencySection]['package'];
- if (!is_array($packageList) || isset($packageList['name'])) {
- $packageList = array($packageList);
- }
- foreach ($packageList as $packageRawData) {
- $package = array();
- $package['name'] = $packageRawData['name'];
- $package['channel'] = $this->convertChannelFromV1x($packageRawData['channel']);
- $package['min_version'] = isset($packageRawData['min']) ? $packageRawData['min'] : null;
- $package['max_version'] = isset($packageRawData['max']) ? $packageRawData['max'] : null;
- array_push($packages, $package);
- }
- }
- }
- }
- }
- $this->setDependencyPackages($packages);
- $this->setDependencyPhpExtensions($extensions);
- // Import contents
- if (isset($data['contents']) && is_array($data['contents']) && is_array($data['contents']['dir'])) {
- // Handle files
- $root = $data['contents']['dir'];
- if (isset($data['contents']['dir']['file'])) {
- $fileList = $data['contents']['dir']['file'];
- if (!is_array($fileList) || isset($fileList['attribs'])) {
- $fileList = array($fileList);
- }
- foreach ($fileList as $fileRawData) {
- $targetName = $fileRawData['attribs']['role'];
- $parentTargetNode = $this->_getNode('target', $this->_packageXml->contents, $targetName);
- $filePath = $fileRawData['attribs']['name'];
- $filePathParts = explode('/', $filePath);
- $fileName = array_pop($filePathParts);
- $parentDirNode = null;
- if (!empty($filePathParts)) {
- $parentDirNode = $parentTargetNode;
- foreach ($filePathParts as $directoryName) {
- $parentDirNode = $this->_getNode('dir', $parentDirNode, $directoryName);
- }
- } else {
- $parentDirNode = $this->_getNode('dir', $parentTargetNode, '.');
- }
- $fileNode = $parentDirNode->addChild('file');
- $fileNode->addAttribute('name', $fileName);
- $fileNode->addAttribute('hash', $fileRawData['attribs']['md5sum']);
- }
- }
- }
- return $this;
- }
- /**
- * Convert package channel in order for it to be compatible with current version of Magento Connect Manager
- *
- * @param string $channel
- *
- * @return string
- */
- public function convertChannelFromV1x($channel)
- {
- $channelMap = array(
- 'connect.magentocommerce.com/community' => 'community',
- 'connect.magentocommerce.com/core' => 'community'
- );
- if (!empty($channel) && isset($channelMap[$channel])) {
- $channel = $channelMap[$channel];
- }
- return $channel;
- }
- }