Version Notes
1.6.0.0
Download this release
Release Info
Developer | Magento Core Team |
Extension | Lib_Mage |
Version | 1.6.0.0 |
Comparing to | |
See all releases |
Version 1.6.0.0
- lib/Mage/Archive.php +222 -0
- lib/Mage/Archive/Abstract.php +84 -0
- lib/Mage/Archive/Bz.php +79 -0
- lib/Mage/Archive/Gz.php +77 -0
- lib/Mage/Archive/Interface.php +53 -0
- lib/Mage/Archive/Tar.php +372 -0
- lib/Mage/Autoload/Simple.php +52 -0
- lib/Mage/Connect/Channel/Generator.php +63 -0
- lib/Mage/Connect/Channel/Parser.php +25 -0
- lib/Mage/Connect/Channel/VO.php +113 -0
- lib/Mage/Connect/Command.php +390 -0
- lib/Mage/Connect/Command/Channels.php +189 -0
- lib/Mage/Connect/Command/Channels_Header.php +105 -0
- lib/Mage/Connect/Command/Config.php +211 -0
- lib/Mage/Connect/Command/Config_Header.php +100 -0
- lib/Mage/Connect/Command/Install.php +448 -0
- lib/Mage/Connect/Command/Install_Header.php +237 -0
- lib/Mage/Connect/Command/Package.php +134 -0
- lib/Mage/Connect/Command/Package_Header.php +67 -0
- lib/Mage/Connect/Command/Registry.php +175 -0
- lib/Mage/Connect/Command/Registry_Header.php +68 -0
- lib/Mage/Connect/Command/Remote.php +226 -0
- lib/Mage/Connect/Command/Remote_Header.php +88 -0
- lib/Mage/Connect/Config.php +265 -0
- lib/Mage/Connect/Converter.php +337 -0
- lib/Mage/Connect/Frontend.php +251 -0
- lib/Mage/Connect/Frontend/CLI.php +441 -0
- lib/Mage/Connect/Ftp.php +494 -0
- lib/Mage/Connect/Loader.php +51 -0
- lib/Mage/Connect/Loader/Ftp.php +121 -0
- lib/Mage/Connect/Package.php +1486 -0
- lib/Mage/Connect/Package/Extension.php +1 -0
- lib/Mage/Connect/Package/Hotfix.php +137 -0
- lib/Mage/Connect/Package/Maintainer.php +0 -0
- lib/Mage/Connect/Package/Reader.php +150 -0
- lib/Mage/Connect/Package/Target.php +126 -0
- lib/Mage/Connect/Package/VO.php +96 -0
- lib/Mage/Connect/Package/Writer.php +209 -0
- lib/Mage/Connect/Packager.php +662 -0
- lib/Mage/Connect/Repository.php +0 -0
- lib/Mage/Connect/Repository/Abstract.php +0 -0
- lib/Mage/Connect/Repository/Channel.php +0 -0
- lib/Mage/Connect/Repository/Channel/Abstract.php +0 -0
- lib/Mage/Connect/Repository/Channel/Commercial.php +0 -0
- lib/Mage/Connect/Repository/Channel/Community.php +0 -0
- lib/Mage/Connect/Repository/Channel/Core.php +0 -0
- lib/Mage/Connect/Repository/Local.php +0 -0
- lib/Mage/Connect/Rest.php +364 -0
- lib/Mage/Connect/Singleconfig.php +865 -0
- lib/Mage/Connect/Structures/Graph.php +248 -0
- lib/Mage/Connect/Structures/Node.php +257 -0
- lib/Mage/Connect/Validator.php +417 -0
- lib/Mage/DB/Exception.php +36 -0
- lib/Mage/DB/Mysqli.php +532 -0
- lib/Mage/Exception.php +35 -0
- lib/Mage/HTTP/Client.php +84 -0
- lib/Mage/HTTP/Client/Curl.php +499 -0
- lib/Mage/HTTP/Client/Socket.php +537 -0
- lib/Mage/HTTP/IClient.php +145 -0
- lib/Mage/System/Args.php +102 -0
- lib/Mage/System/Dirs.php +82 -0
- lib/Mage/Xml/Generator.php +90 -0
- lib/Mage/Xml/Parser.php +91 -0
- package.xml +18 -0
lib/Mage/Archive.php
ADDED
@@ -0,0 +1,222 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Archive
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with archives
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Archive
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Archive
|
35 |
+
{
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Archiver is used for compress.
|
39 |
+
*/
|
40 |
+
const DEFAULT_ARCHIVER = 'gz';
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Default packer for directory.
|
44 |
+
*/
|
45 |
+
const TAPE_ARCHIVER = 'tar';
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Current archiver is used for compress.
|
49 |
+
*
|
50 |
+
* @var Mage_Archiver_Tar|Mage_Archiver_Gz|Mage_Archiver_Bz
|
51 |
+
*/
|
52 |
+
protected $_archiver=null;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Accessible formats for compress.
|
56 |
+
*
|
57 |
+
* @var array
|
58 |
+
*/
|
59 |
+
protected $_formats = array(
|
60 |
+
'tar' => 'tar',
|
61 |
+
'gz' => 'gz',
|
62 |
+
'gzip' => 'gz',
|
63 |
+
'tgz' => 'tar.gz',
|
64 |
+
'tgzip' => 'tar.gz',
|
65 |
+
'bz' => 'bz',
|
66 |
+
'bzip' => 'bz',
|
67 |
+
'bzip2' => 'bz',
|
68 |
+
'bz2' => 'bz',
|
69 |
+
'tbz' => 'tar.bz',
|
70 |
+
'tbzip' => 'tar.bz',
|
71 |
+
'tbz2' => 'tar.bz',
|
72 |
+
'tbzip2' => 'tar.bz');
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Create object of current archiver by $extension.
|
76 |
+
*
|
77 |
+
* @param string $extension
|
78 |
+
* @return Mage_Archiver_Tar|Mage_Archiver_Gz|Mage_Archiver_Bz
|
79 |
+
*/
|
80 |
+
protected function _getArchiver($extension)
|
81 |
+
{
|
82 |
+
if(array_key_exists(strtolower($extension), $this->_formats)) {
|
83 |
+
$format = $this->_formats[$extension];
|
84 |
+
} else {
|
85 |
+
$format = self::DEFAULT_ARCHIVER;
|
86 |
+
}
|
87 |
+
$class = 'Mage_Archive_'.ucfirst($format);
|
88 |
+
$this->_archiver = new $class();
|
89 |
+
return $this->_archiver;
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Split current format to list of archivers.
|
94 |
+
*
|
95 |
+
* @param string $source
|
96 |
+
* @return array
|
97 |
+
*/
|
98 |
+
protected function _getArchivers($source)
|
99 |
+
{
|
100 |
+
$ext = pathinfo($source, PATHINFO_EXTENSION);
|
101 |
+
if(!isset($this->_formats[$ext])) {
|
102 |
+
return array();
|
103 |
+
}
|
104 |
+
$format = $this->_formats[$ext];
|
105 |
+
if ($format) {
|
106 |
+
$archivers = explode('.', $format);
|
107 |
+
return $archivers;
|
108 |
+
}
|
109 |
+
return array();
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Pack file or directory to archivers are parsed from extension.
|
114 |
+
*
|
115 |
+
* @param string $source
|
116 |
+
* @param string $destination
|
117 |
+
* @param boolean $skipRoot skip first level parent
|
118 |
+
* @return string Path to file
|
119 |
+
*/
|
120 |
+
public function pack($source, $destination='packed.tgz', $skipRoot=false)
|
121 |
+
{
|
122 |
+
$archivers = $this->_getArchivers($destination);
|
123 |
+
$interimSource = '';
|
124 |
+
for ($i=0; $i<count($archivers); $i++ ) {
|
125 |
+
if ($i == (count($archivers) - 1)) {
|
126 |
+
$packed = $destination;
|
127 |
+
} else {
|
128 |
+
$packed = dirname($destination) . DS . '~tmp-'. microtime(true) . $archivers[$i] . '.' . $archivers[$i];
|
129 |
+
}
|
130 |
+
$source = $this->_getArchiver($archivers[$i])->pack($source, $packed, $skipRoot);
|
131 |
+
if ($interimSource && $i < count($archivers)) {
|
132 |
+
unlink($interimSource);
|
133 |
+
}
|
134 |
+
$interimSource = $source;
|
135 |
+
}
|
136 |
+
return $source;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Unpack file from archivers are parsed from extension.
|
141 |
+
* If $tillTar == true unpack file from archivers till
|
142 |
+
* meet TAR archiver.
|
143 |
+
*
|
144 |
+
* @param string $source
|
145 |
+
* @param string $destination
|
146 |
+
* @param boolean $tillTar
|
147 |
+
* @return string Path to file
|
148 |
+
*/
|
149 |
+
public function unpack($source, $destination='.', $tillTar=false, $clearInterm = true)
|
150 |
+
{
|
151 |
+
$archivers = $this->_getArchivers($source);
|
152 |
+
$interimSource = '';
|
153 |
+
for ($i=count($archivers)-1; $i>=0; $i--) {
|
154 |
+
if ($tillTar && $archivers[$i] == self::TAPE_ARCHIVER) {
|
155 |
+
break;
|
156 |
+
}
|
157 |
+
if ($i == 0) {
|
158 |
+
$packed = rtrim($destination, DS) . DS;
|
159 |
+
} else {
|
160 |
+
$packed = rtrim($destination, DS) . DS . '~tmp-'. microtime(true) . $archivers[$i-1] . '.' . $archivers[$i-1];
|
161 |
+
}
|
162 |
+
$source = $this->_getArchiver($archivers[$i])->unpack($source, $packed);
|
163 |
+
|
164 |
+
//var_dump($packed, $source);
|
165 |
+
|
166 |
+
if ($clearInterm && $interimSource && $i >= 0) {
|
167 |
+
unlink($interimSource);
|
168 |
+
}
|
169 |
+
$interimSource = $source;
|
170 |
+
}
|
171 |
+
return $source;
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Extract one file from TAR (Tape Archiver).
|
176 |
+
*
|
177 |
+
* @param string $file
|
178 |
+
* @param string $source
|
179 |
+
* @param string $destination
|
180 |
+
* @return string Path to file
|
181 |
+
*/
|
182 |
+
public function extract($file, $source, $destination='.')
|
183 |
+
{
|
184 |
+
$tarFile = $this->unpack($source, $destination, true);
|
185 |
+
$resFile = $this->_getArchiver(self::TAPE_ARCHIVER)->extract($file, $tarFile, $destination);
|
186 |
+
if (!$this->isTar($source)) {
|
187 |
+
unlink($tarFile);
|
188 |
+
}
|
189 |
+
return $resFile;
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Check file is archive.
|
194 |
+
*
|
195 |
+
* @param string $file
|
196 |
+
* @return boolean
|
197 |
+
*/
|
198 |
+
public function isArchive($file)
|
199 |
+
{
|
200 |
+
$archivers = $this->_getArchivers($file);
|
201 |
+
if (count($archivers)) {
|
202 |
+
return true;
|
203 |
+
}
|
204 |
+
return false;
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Check file is TAR.
|
209 |
+
*
|
210 |
+
* @param mixed $file
|
211 |
+
* @return boolean
|
212 |
+
*/
|
213 |
+
public function isTar($file)
|
214 |
+
{
|
215 |
+
$archivers = $this->_getArchivers($file);
|
216 |
+
if (count($archivers)==1 && $archivers[0] == self::TAPE_ARCHIVER) {
|
217 |
+
return true;
|
218 |
+
}
|
219 |
+
return false;
|
220 |
+
}
|
221 |
+
|
222 |
+
}
|
lib/Mage/Archive/Abstract.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Archive
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with archives
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Archive
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Archive_Abstract
|
35 |
+
{
|
36 |
+
/**
|
37 |
+
* Write data to file. If file can't be opened,
|
38 |
+
*
|
39 |
+
* @param string $destination
|
40 |
+
* @param string $data
|
41 |
+
* @return boolean
|
42 |
+
*/
|
43 |
+
protected function _writeFile($destination, $data)
|
44 |
+
{
|
45 |
+
if(false === file_put_contents($destination, $data)) {
|
46 |
+
throw new Mage_Exception("Can't write to file: " . $destination);
|
47 |
+
}
|
48 |
+
return true;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Read data from file. If file can't be opened, throw to exception.
|
53 |
+
*
|
54 |
+
* @param string $source
|
55 |
+
* @return string
|
56 |
+
*/
|
57 |
+
protected function _readFile($source)
|
58 |
+
{
|
59 |
+
$data = '';
|
60 |
+
if (is_file($source) && is_readable($source)) {
|
61 |
+
$data = @file_get_contents($source);
|
62 |
+
if ($data === false) {
|
63 |
+
throw new Mage_Exception("Can't get contents from: " . $source);
|
64 |
+
}
|
65 |
+
}
|
66 |
+
return $data;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Get file name from source (URI) without last extension.
|
71 |
+
*
|
72 |
+
* @param string $source
|
73 |
+
* @return string
|
74 |
+
*/
|
75 |
+
public function getFilename($source, $withExtension=false)
|
76 |
+
{
|
77 |
+
$file = str_replace(dirname($source) . DS, '', $source);
|
78 |
+
if (!$withExtension) {
|
79 |
+
$file = substr($file, 0, strrpos($file, '.'));
|
80 |
+
}
|
81 |
+
return $file;
|
82 |
+
}
|
83 |
+
|
84 |
+
}
|
lib/Mage/Archive/Bz.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Archive
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with bzip2 archives
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Archive
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Archive_Bz extends Mage_Archive_Abstract implements Mage_Archive_Interface
|
35 |
+
{
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Pack file by BZIP2 compressor.
|
39 |
+
*
|
40 |
+
* @param string $source
|
41 |
+
* @param string $destination
|
42 |
+
* @return string
|
43 |
+
*/
|
44 |
+
public function pack($source, $destination)
|
45 |
+
{
|
46 |
+
$data = $this->_readFile($source);
|
47 |
+
$bzData = bzcompress($data, 9);
|
48 |
+
$this->_writeFile($destination, $bzData);
|
49 |
+
return $destination;
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Unpack file by BZIP2 compressor.
|
54 |
+
*
|
55 |
+
* @param string $source
|
56 |
+
* @param string $destination
|
57 |
+
* @return string
|
58 |
+
*/
|
59 |
+
public function unpack($source, $destination)
|
60 |
+
{
|
61 |
+
$data = '';
|
62 |
+
$bzPointer = bzopen($source, 'r' );
|
63 |
+
if (empty($bzPointer)) {
|
64 |
+
throw new Exception('Can\'t open BZ archive : ' . $source);
|
65 |
+
}
|
66 |
+
while (!feof($bzPointer)) {
|
67 |
+
$data .= bzread($bzPointer, 131072);
|
68 |
+
}
|
69 |
+
bzclose($bzPointer);
|
70 |
+
if (is_dir($destination)) {
|
71 |
+
$file = $this->getFilename($source);
|
72 |
+
$destination = $destination . $file;
|
73 |
+
}
|
74 |
+
echo $destination;
|
75 |
+
$this->_writeFile($destination, $data);
|
76 |
+
return $destination;
|
77 |
+
}
|
78 |
+
|
79 |
+
}
|
lib/Mage/Archive/Gz.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Archive
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with gz archives
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Archive
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Archive_Gz extends Mage_Archive_Abstract implements Mage_Archive_Interface
|
35 |
+
{
|
36 |
+
/**
|
37 |
+
* Pack file by GZ compressor.
|
38 |
+
*
|
39 |
+
* @param string $source
|
40 |
+
* @param string $destination
|
41 |
+
* @return string
|
42 |
+
*/
|
43 |
+
public function pack($source, $destination)
|
44 |
+
{
|
45 |
+
$data = $this->_readFile($source);
|
46 |
+
$gzData = gzencode($data, 9);
|
47 |
+
$this->_writeFile($destination, $gzData);
|
48 |
+
return $destination;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Unpack file by GZ compressor.
|
53 |
+
*
|
54 |
+
* @param string $source
|
55 |
+
* @param string $destination
|
56 |
+
* @return string
|
57 |
+
*/
|
58 |
+
public function unpack($source, $destination)
|
59 |
+
{
|
60 |
+
$gzPointer = gzopen($source, 'r' );
|
61 |
+
if (empty($gzPointer)) {
|
62 |
+
throw new Mage_Exception('Can\'t open GZ archive : ' . $source);
|
63 |
+
}
|
64 |
+
$data = '';
|
65 |
+
while (!gzeof($gzPointer)) {
|
66 |
+
$data .= gzread($gzPointer, 131072);
|
67 |
+
}
|
68 |
+
gzclose($gzPointer);
|
69 |
+
if (is_dir($destination)) {
|
70 |
+
$file = $this->getFilename($source);
|
71 |
+
$destination = $destination . $file;
|
72 |
+
}
|
73 |
+
$this->_writeFile($destination, $data);
|
74 |
+
return $destination;
|
75 |
+
}
|
76 |
+
|
77 |
+
}
|
lib/Mage/Archive/Interface.php
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Archive
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Interface for work with archives
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Archive
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
interface Mage_Archive_Interface
|
35 |
+
{
|
36 |
+
/**
|
37 |
+
* Pack file or directory.
|
38 |
+
*
|
39 |
+
* @param string $source
|
40 |
+
* @param string $destination
|
41 |
+
* @return string
|
42 |
+
*/
|
43 |
+
public function pack($source, $destination);
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Unpack file or directory.
|
47 |
+
*
|
48 |
+
* @param string $source
|
49 |
+
* @param string $destination
|
50 |
+
* @return string
|
51 |
+
*/
|
52 |
+
public function unpack($source, $destination);
|
53 |
+
}
|
lib/Mage/Archive/Tar.php
ADDED
@@ -0,0 +1,372 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Archive
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with tar archives
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Archive
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Archive_Tar extends Mage_Archive_Abstract implements Mage_Archive_Interface
|
35 |
+
{
|
36 |
+
/**
|
37 |
+
* Constant is used for parse tar's header.
|
38 |
+
*/
|
39 |
+
const FORMAT_PARSE_HEADER = 'a100name/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1type/a100symlink/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix/a12closer';
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Keep file or directory for packing.
|
43 |
+
*
|
44 |
+
* @var string
|
45 |
+
*/
|
46 |
+
protected $_currentFile;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Keep path to file or directory for packing.
|
50 |
+
*
|
51 |
+
* @var mixed
|
52 |
+
*/
|
53 |
+
protected $_currentPath;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Skip first level parent directory. Example:
|
57 |
+
* use test/fip.php instead test/test/fip.php;
|
58 |
+
*
|
59 |
+
* @var mixed
|
60 |
+
*/
|
61 |
+
protected $_skipRoot;
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Set option that define ability skip first catalog level.
|
65 |
+
*
|
66 |
+
* @param mixed $skipRoot
|
67 |
+
* @return Mage_Archive_Tar
|
68 |
+
*/
|
69 |
+
protected function _setSkipRoot($skipRoot)
|
70 |
+
{
|
71 |
+
$this->_skipRoot = $skipRoot;
|
72 |
+
return $this;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Set file which is packing.
|
77 |
+
*
|
78 |
+
* @param string $file
|
79 |
+
* @return Mage_Archive_Tar
|
80 |
+
*/
|
81 |
+
protected function _setCurrentFile($file)
|
82 |
+
{
|
83 |
+
$this->_currentFile = $file .((is_dir($file) && substr($file, -1)!=DS)?DS:'');
|
84 |
+
return $this;
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Retrieve file which is packing.
|
89 |
+
*
|
90 |
+
* @return string
|
91 |
+
*/
|
92 |
+
protected function _getCurrentFile()
|
93 |
+
{
|
94 |
+
return $this->_currentFile;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Set path to file which is packing.
|
99 |
+
*
|
100 |
+
* @param string $path
|
101 |
+
* @return Mage_Archive_Tar
|
102 |
+
*/
|
103 |
+
protected function _setCurrentPath($path)
|
104 |
+
{
|
105 |
+
if ($this->_skipRoot && is_dir($path)) {
|
106 |
+
$this->_currentPath = $path.(substr($path, -1)!=DS?DS:'');
|
107 |
+
} else {
|
108 |
+
$this->_currentPath = dirname($path) . DS;
|
109 |
+
}
|
110 |
+
return $this;
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Retrieve path to file which is packing.
|
115 |
+
*
|
116 |
+
* @return string
|
117 |
+
*/
|
118 |
+
protected function _getCurrentPath()
|
119 |
+
{
|
120 |
+
return $this->_currentPath;
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Walk through directory and add to tar file or directory.
|
125 |
+
* Result is packed string on TAR format.
|
126 |
+
*
|
127 |
+
* @param boolean $skipRoot
|
128 |
+
* @return string
|
129 |
+
*/
|
130 |
+
protected function _packToTar($skipRoot=false)
|
131 |
+
{
|
132 |
+
$file = $this->_getCurrentFile();
|
133 |
+
$header = '';
|
134 |
+
$data = '';
|
135 |
+
if (!$skipRoot) {
|
136 |
+
$header = $this->_composeHeader();
|
137 |
+
$data = $this->_readFile($file);
|
138 |
+
$data = str_pad($data, floor(((is_dir($file) ? 0 : filesize($file)) + 512 - 1) / 512) * 512, "\0");
|
139 |
+
}
|
140 |
+
$sub = '';
|
141 |
+
if (is_dir($file)) {
|
142 |
+
$treeDir = scandir($file);
|
143 |
+
if (empty($treeDir)) {
|
144 |
+
throw new Mage_Exception('Can\'t scan dir: ' . $file);
|
145 |
+
}
|
146 |
+
array_shift($treeDir); /* remove './'*/
|
147 |
+
array_shift($treeDir); /* remove '../'*/
|
148 |
+
foreach ($treeDir as $item) {
|
149 |
+
$sub .= $this->_setCurrentFile($file.$item)->_packToTar(false);
|
150 |
+
}
|
151 |
+
}
|
152 |
+
$tarData = $header . $data . $sub;
|
153 |
+
$tarData = str_pad($tarData, floor((strlen($tarData) - 1) / 1536) * 1536, "\0");
|
154 |
+
return $tarData;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Compose header for current file in TAR format.
|
159 |
+
* If length of file's name greater 100 characters,
|
160 |
+
* method breaks header to two pieces. First conatins
|
161 |
+
* header and data with long name. Second contain only header.
|
162 |
+
*
|
163 |
+
* @param boolean $long
|
164 |
+
* @return string
|
165 |
+
*/
|
166 |
+
protected function _composeHeader($long = false)
|
167 |
+
{
|
168 |
+
$file = $this->_getCurrentFile();
|
169 |
+
$path = $this->_getCurrentPath();
|
170 |
+
$infoFile = stat($file);
|
171 |
+
$nameFile = str_replace($path, '', $file);
|
172 |
+
$nameFile = str_replace('\\', '/', $nameFile);
|
173 |
+
$packedHeader = '';
|
174 |
+
$longHeader = '';
|
175 |
+
if (!$long && strlen($nameFile)>100) {
|
176 |
+
$longHeader = $this->_composeHeader(true);
|
177 |
+
$longHeader .= str_pad($nameFile, floor((strlen($nameFile) + 512 - 1) / 512) * 512, "\0");
|
178 |
+
}
|
179 |
+
$header = array();
|
180 |
+
$header['100-name'] = $long?'././@LongLink':substr($nameFile, 0, 100);
|
181 |
+
$header['8-mode'] = $long?' ':str_pad(substr(sprintf("%07o", $infoFile['mode']),-4), 6, '0', STR_PAD_LEFT);
|
182 |
+
$header['8-uid'] = $long || $infoFile['uid']==0?"\0\0\0\0\0\0\0":sprintf("%07o", $infoFile['uid']);
|
183 |
+
$header['8-gid'] = $long || $infoFile['gid']==0?"\0\0\0\0\0\0\0":sprintf("%07o", $infoFile['gid']);
|
184 |
+
$header['12-size'] = $long?sprintf("%011o", strlen($nameFile)):sprintf("%011o", is_dir($file) ? 0 : filesize($file));
|
185 |
+
$header['12-mtime'] = $long?'00000000000':sprintf("%011o", $infoFile['mtime']);
|
186 |
+
$header['8-check'] = sprintf('% 8s', '');
|
187 |
+
$header['1-type'] = $long?'L':(is_link($file) ? 2 : is_dir ($file) ? 5 : 0);
|
188 |
+
$header['100-symlink'] = is_link($file) == 2 ? readlink($item) : '';
|
189 |
+
$header['6-magic'] = 'ustar ';
|
190 |
+
$header['2-version'] = ' ';
|
191 |
+
$a=function_exists('posix_getpwuid')?posix_getpwuid (fileowner($file)):array('name'=>'');
|
192 |
+
$header['32-uname'] = $a['name'];
|
193 |
+
$a=function_exists('posix_getgrgid')?posix_getgrgid (filegroup($file)):array('name'=>'');
|
194 |
+
$header['32-gname'] = $a['name'];
|
195 |
+
$header['8-devmajor'] = '';
|
196 |
+
$header['8-devminor'] = '';
|
197 |
+
$header['155-prefix'] = '';
|
198 |
+
$header['12-closer'] = '';
|
199 |
+
|
200 |
+
$packedHeader = '';
|
201 |
+
foreach ($header as $key=>$element) {
|
202 |
+
$length = explode('-', $key);
|
203 |
+
$packedHeader .= pack('a' . $length[0], $element);
|
204 |
+
}
|
205 |
+
|
206 |
+
$checksum = 0;
|
207 |
+
for ($i = 0; $i < 512; $i++) {
|
208 |
+
$checksum += ord(substr($packedHeader, $i, 1));
|
209 |
+
}
|
210 |
+
$packedHeader = substr_replace($packedHeader, sprintf("%07o", $checksum)."\0", 148, 8);
|
211 |
+
|
212 |
+
return $longHeader . $packedHeader;
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Read TAR string from file, and unpacked it.
|
217 |
+
* Create files and directories information about discribed
|
218 |
+
* in the string.
|
219 |
+
*
|
220 |
+
* @param string $destination path to file is unpacked
|
221 |
+
* @return array list of files
|
222 |
+
*/
|
223 |
+
protected function _unpackCurrentTar($destination)
|
224 |
+
{
|
225 |
+
$file = $this->_getCurrentFile();
|
226 |
+
$pointer = fopen($file, 'r');
|
227 |
+
if (empty($pointer)) {
|
228 |
+
throw new Mage_Exception('Can\'t open file: ' . $file);
|
229 |
+
}
|
230 |
+
$list = array();
|
231 |
+
while (!feof($pointer)) {
|
232 |
+
$header = $this->_parseHeader($pointer);
|
233 |
+
if ($header) {
|
234 |
+
$currentFile = $destination . $header['name'];
|
235 |
+
if ($header['type']=='5' && @mkdir($currentFile, 0777, true)) {
|
236 |
+
$list[] = $currentFile . DS;
|
237 |
+
} elseif (in_array($header['type'], array("0",chr(0), ''))) {
|
238 |
+
$dirname = dirname($currentFile);
|
239 |
+
if(!file_exists($dirname)) {
|
240 |
+
@mkdir($dirname, 0777, true);
|
241 |
+
}
|
242 |
+
$this->_writeFile($currentFile, $header['data']);
|
243 |
+
$list[] = $currentFile;
|
244 |
+
}
|
245 |
+
}
|
246 |
+
}
|
247 |
+
fclose($pointer);
|
248 |
+
return $list;
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Get header from TAR string and unpacked it by format.
|
253 |
+
*
|
254 |
+
* @param resource $pointer
|
255 |
+
* @return string
|
256 |
+
*/
|
257 |
+
protected function _parseHeader(&$pointer)
|
258 |
+
{
|
259 |
+
$firstLine = fread($pointer, 512);
|
260 |
+
|
261 |
+
if (strlen($firstLine)<512){
|
262 |
+
return false;
|
263 |
+
}
|
264 |
+
|
265 |
+
$fmt = self::FORMAT_PARSE_HEADER;
|
266 |
+
$header = unpack ($fmt, $firstLine);
|
267 |
+
|
268 |
+
|
269 |
+
$header['mode']=$header['mode']+0;
|
270 |
+
$header['uid']=octdec($header['uid']);
|
271 |
+
$header['gid']=octdec($header['gid']);
|
272 |
+
$header['size']=octdec($header['size']);
|
273 |
+
$header['mtime']=octdec($header['mtime']);
|
274 |
+
$header['checksum']=octdec($header['checksum']);
|
275 |
+
|
276 |
+
if ($header['type'] == "5") {
|
277 |
+
$header['size'] = 0;
|
278 |
+
}
|
279 |
+
|
280 |
+
$checksum = 0;
|
281 |
+
$firstLine = substr_replace($firstLine, ' ', 148, 8);
|
282 |
+
for ($i = 0; $i < 512; $i++) {
|
283 |
+
$checksum += ord(substr($firstLine, $i, 1));
|
284 |
+
}
|
285 |
+
|
286 |
+
$isUstar = 'ustar' == strtolower(substr($header['magic'], 0, 5));
|
287 |
+
|
288 |
+
$checksumOk = $header['checksum'] == $checksum;
|
289 |
+
if (isset($header['name']) && $checksumOk) {
|
290 |
+
if ($header['name'] == '././@LongLink' && $header['type'] == 'L') {
|
291 |
+
$realName = substr(fread($pointer, floor(($header['size'] + 512 - 1) / 512) * 512), 0, $header['size']);
|
292 |
+
$headerMain = $this->_parseHeader($pointer);
|
293 |
+
$headerMain['name'] = $realName;
|
294 |
+
return $headerMain;
|
295 |
+
} else {
|
296 |
+
if ($header['size']>0) {
|
297 |
+
$header['data'] = substr(fread($pointer, floor(($header['size'] + 512 - 1) / 512) * 512), 0, $header['size']);
|
298 |
+
} else {
|
299 |
+
$header['data'] = '';
|
300 |
+
}
|
301 |
+
return $header;
|
302 |
+
}
|
303 |
+
}
|
304 |
+
return false;
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Pack file to TAR (Tape Archiver).
|
309 |
+
*
|
310 |
+
* @param string $source
|
311 |
+
* @param string $destination
|
312 |
+
* @param boolean $skipRoot
|
313 |
+
* @return string
|
314 |
+
*/
|
315 |
+
public function pack($source, $destination, $skipRoot=false)
|
316 |
+
{
|
317 |
+
$this->_setSkipRoot($skipRoot);
|
318 |
+
$source = realpath($source);
|
319 |
+
$tarData = $this->_setCurrentPath($source)
|
320 |
+
->_setCurrentFile($source)
|
321 |
+
->_packToTar($skipRoot);
|
322 |
+
$this->_writeFile($destination, $tarData);
|
323 |
+
return $destination;
|
324 |
+
}
|
325 |
+
|
326 |
+
/**
|
327 |
+
* Unpack file from TAR (Tape Archiver).
|
328 |
+
*
|
329 |
+
* @param string $source
|
330 |
+
* @param string $destination
|
331 |
+
* @return string
|
332 |
+
*/
|
333 |
+
public function unpack($source, $destination)
|
334 |
+
{
|
335 |
+
$tempFile = $destination . DS . '~tmp-'.microtime(true).'.tar';
|
336 |
+
$data = $this->_readFile($source);
|
337 |
+
$this->_writeFile($tempFile, $data);
|
338 |
+
$this->_setCurrentFile($tempFile)
|
339 |
+
->_setCurrentPath($tempFile)
|
340 |
+
->_unpackCurrentTar($destination);
|
341 |
+
unlink($tempFile);
|
342 |
+
return $destination;
|
343 |
+
}
|
344 |
+
|
345 |
+
/**
|
346 |
+
* Extract one file from TAR (Tape Archiver).
|
347 |
+
*
|
348 |
+
* @param string $file
|
349 |
+
* @param string $source
|
350 |
+
* @param string $destination
|
351 |
+
* @return string
|
352 |
+
*/
|
353 |
+
public function extract($file, $source, $destination)
|
354 |
+
{
|
355 |
+
$pointer = fopen($source, 'r');
|
356 |
+
if (empty($pointer)) {
|
357 |
+
throw new Mage_Exception('Can\'t open file: '.$source);
|
358 |
+
}
|
359 |
+
$list = array();
|
360 |
+
$extractedFile = '';
|
361 |
+
while (!feof($pointer)) {
|
362 |
+
$header = $this->_parseHeader($pointer);
|
363 |
+
if ($header['name'] == $file) {
|
364 |
+
$extractedFile = $destination . basename($header['name']);
|
365 |
+
$this->_writeFile($extractedFile, $header['data']);
|
366 |
+
break;
|
367 |
+
}
|
368 |
+
}
|
369 |
+
fclose($pointer);
|
370 |
+
return $extractedFile;
|
371 |
+
}
|
372 |
+
}
|
lib/Mage/Autoload/Simple.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
class Mage_Autoload_Simple
|
28 |
+
{
|
29 |
+
private static $_instance;
|
30 |
+
|
31 |
+
public static function instance()
|
32 |
+
{
|
33 |
+
if (!self::$_instance) {
|
34 |
+
$class = __CLASS__;
|
35 |
+
self::$_instance = new $class();
|
36 |
+
}
|
37 |
+
return self::$_instance;
|
38 |
+
}
|
39 |
+
|
40 |
+
public static function register()
|
41 |
+
{
|
42 |
+
spl_autoload_register(array(self::instance(), 'autoload'));
|
43 |
+
}
|
44 |
+
|
45 |
+
public function autoload($class)
|
46 |
+
{
|
47 |
+
$classFile = str_replace(' ', DIRECTORY_SEPARATOR, ucwords(str_replace('_', ' ', $class)));
|
48 |
+
$classFile.= '.php';
|
49 |
+
@include $classFile;
|
50 |
+
}
|
51 |
+
|
52 |
+
}
|
lib/Mage/Connect/Channel/Generator.php
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
class Mage_Connect_Channel_Generator extends Mage_Xml_Generator
|
28 |
+
{
|
29 |
+
protected $_file = 'channel.xml';
|
30 |
+
protected $_generator = null;
|
31 |
+
|
32 |
+
public function __construct($file='')
|
33 |
+
{
|
34 |
+
if ($file) {
|
35 |
+
$this->_file = $file;
|
36 |
+
}
|
37 |
+
return $this;
|
38 |
+
}
|
39 |
+
|
40 |
+
public function getFile()
|
41 |
+
{
|
42 |
+
return $this->_file;
|
43 |
+
}
|
44 |
+
|
45 |
+
public function getGenerator()
|
46 |
+
{
|
47 |
+
if (is_null($this->_generator)) {
|
48 |
+
$this->_generator = new Mage_Xml_Generator();
|
49 |
+
}
|
50 |
+
return $this->_generator;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* @param array $content
|
55 |
+
*/
|
56 |
+
public function save($content)
|
57 |
+
{
|
58 |
+
$xmlContent = $this->getGenerator()
|
59 |
+
->arrayToXml($content)
|
60 |
+
->save($this->getFile());
|
61 |
+
return $this;
|
62 |
+
}
|
63 |
+
}
|
lib/Mage/Connect/Channel/Parser.php
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
lib/Mage/Connect/Channel/VO.php
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
|
28 |
+
class Mage_Connect_Channel_VO implements Iterator
|
29 |
+
{
|
30 |
+
|
31 |
+
private $_validator = null;
|
32 |
+
|
33 |
+
protected $properties = array(
|
34 |
+
'name' => '',
|
35 |
+
'uri' => '',
|
36 |
+
'summary' => '',
|
37 |
+
);
|
38 |
+
|
39 |
+
public function rewind() {
|
40 |
+
reset($this->properties);
|
41 |
+
}
|
42 |
+
|
43 |
+
public function valid() {
|
44 |
+
return current($this->properties) !== false;
|
45 |
+
}
|
46 |
+
|
47 |
+
public function key() {
|
48 |
+
return key($this->properties);
|
49 |
+
}
|
50 |
+
|
51 |
+
public function current() {
|
52 |
+
return current($this->properties);
|
53 |
+
}
|
54 |
+
|
55 |
+
public function next() {
|
56 |
+
next($this->properties);
|
57 |
+
}
|
58 |
+
|
59 |
+
public function __get($var)
|
60 |
+
{
|
61 |
+
if (isset($this->properties[$var])) {
|
62 |
+
return $this->properties[$var];
|
63 |
+
}
|
64 |
+
return null;
|
65 |
+
}
|
66 |
+
|
67 |
+
public function __set($var, $value)
|
68 |
+
{
|
69 |
+
if (is_string($value)) {
|
70 |
+
$value = trim($value);
|
71 |
+
}
|
72 |
+
if (isset($this->properties[$var])) {
|
73 |
+
if ($value === null) {
|
74 |
+
$value = '';
|
75 |
+
}
|
76 |
+
$this->properties[$var] = $value;
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
public function toArray()
|
81 |
+
{
|
82 |
+
return array('channel' => $this->properties);
|
83 |
+
}
|
84 |
+
|
85 |
+
public function fromArray(array $arr)
|
86 |
+
{
|
87 |
+
foreach($arr as $k=>$v) {
|
88 |
+
$this->$k = $v;
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
|
93 |
+
private function validator()
|
94 |
+
{
|
95 |
+
if(is_null($this->_validator)) {
|
96 |
+
$this->_validator = new Mage_Connect_Validator();
|
97 |
+
}
|
98 |
+
return $this->_validator;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
Stub for validation result
|
103 |
+
*/
|
104 |
+
public function validate()
|
105 |
+
{
|
106 |
+
$v = $this->validator();
|
107 |
+
if(!$v->validatePackageName($this->name)) {
|
108 |
+
return false;
|
109 |
+
}
|
110 |
+
return true;
|
111 |
+
}
|
112 |
+
|
113 |
+
}
|
lib/Mage/Connect/Command.php
ADDED
@@ -0,0 +1,390 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
|
28 |
+
class Mage_Connect_Command
|
29 |
+
{
|
30 |
+
/**
|
31 |
+
* All commands list
|
32 |
+
* @var array
|
33 |
+
*/
|
34 |
+
protected static $_commandsAll = array();
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Commands list hash (key=class)
|
38 |
+
* @var array
|
39 |
+
*/
|
40 |
+
protected static $_commandsByClass = array();
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Frontend object
|
44 |
+
* @var Mage_Connect_Fro
|
45 |
+
*/
|
46 |
+
protected static $_frontend = null;
|
47 |
+
protected static $_config = null;
|
48 |
+
protected static $_registry = null;
|
49 |
+
protected static $_validator = null;
|
50 |
+
protected static $_rest = null;
|
51 |
+
protected static $_sconfig = null;
|
52 |
+
|
53 |
+
protected $_data;
|
54 |
+
protected $_class;
|
55 |
+
protected static $_packager = null;
|
56 |
+
|
57 |
+
protected static $_return = array();
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Constructor
|
61 |
+
*
|
62 |
+
*/
|
63 |
+
public function __construct()
|
64 |
+
{
|
65 |
+
$class = $this->_class = get_class($this);
|
66 |
+
if(__CLASS__ == $class) {
|
67 |
+
throw new Exception("You shouldn't instantiate {$class} directly!");
|
68 |
+
}
|
69 |
+
$this->commandsInfo = self::$_commandsByClass[$class];
|
70 |
+
}
|
71 |
+
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Get command info (static)
|
75 |
+
* @param string $name command name
|
76 |
+
* @return array/bool
|
77 |
+
*/
|
78 |
+
public static function commandInfo($name)
|
79 |
+
{
|
80 |
+
$name = strtolower($name);
|
81 |
+
if(!isset(self::$_commandsAll[$name])) {
|
82 |
+
return false;
|
83 |
+
}
|
84 |
+
return self::$_commandsAll[$name];
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Get command info for current command object
|
89 |
+
* @param string $name
|
90 |
+
* @return array/bool
|
91 |
+
*/
|
92 |
+
|
93 |
+
public function getCommandInfo($name)
|
94 |
+
{
|
95 |
+
if(!isset(self::$_commandsByClass[$this->_class][$name])) {
|
96 |
+
return false;
|
97 |
+
}
|
98 |
+
return self::$_commandsByClass[$this->_class][$name];
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Run command
|
103 |
+
* @param string $command
|
104 |
+
* @param string $options
|
105 |
+
* @param string $params
|
106 |
+
* @throws Exception if there's no needed method
|
107 |
+
* @return mixed
|
108 |
+
*/
|
109 |
+
public function run($command, $options, $params)
|
110 |
+
{
|
111 |
+
$data = $this->getCommandInfo($command);
|
112 |
+
$method = $data['function'];
|
113 |
+
if(! method_exists($this, $method)) {
|
114 |
+
throw new Exception("$method does't exist in class ".$this->_class);
|
115 |
+
}
|
116 |
+
return $this->$method($command, $options, $params);
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Static functions
|
121 |
+
*/
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Static
|
125 |
+
* @param $commandName
|
126 |
+
* @return unknown_type
|
127 |
+
*/
|
128 |
+
public static function getInstance($commandName)
|
129 |
+
{
|
130 |
+
if(!isset(self::$_commandsAll[$commandName])) {
|
131 |
+
throw new UnexpectedValueException("Cannot find command $commandName");
|
132 |
+
}
|
133 |
+
$currentCommand = self::$_commandsAll[$commandName];
|
134 |
+
return new $currentCommand['class']();
|
135 |
+
}
|
136 |
+
|
137 |
+
|
138 |
+
public static function setSconfig($obj)
|
139 |
+
{
|
140 |
+
self::$_sconfig = $obj;
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
*
|
145 |
+
* @return Mage_Connect_Singleconfig
|
146 |
+
*/
|
147 |
+
public function getSconfig()
|
148 |
+
{
|
149 |
+
return self::$_sconfig;
|
150 |
+
}
|
151 |
+
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Sets frontend object for all commands
|
155 |
+
*
|
156 |
+
* @param Mage_Connect_Frontend $obj
|
157 |
+
* @return void
|
158 |
+
*/
|
159 |
+
public static function setFrontendObject($obj)
|
160 |
+
{
|
161 |
+
self::$_frontend = $obj;
|
162 |
+
}
|
163 |
+
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Set config object for all commands
|
167 |
+
* @param Mage_Connect_Config $obj
|
168 |
+
* @return void
|
169 |
+
*/
|
170 |
+
public static function setConfigObject($obj)
|
171 |
+
{
|
172 |
+
self::$_config = $obj;
|
173 |
+
}
|
174 |
+
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Non-static getter for config
|
178 |
+
* @return Mage_Connect_Config
|
179 |
+
*/
|
180 |
+
public function config()
|
181 |
+
{
|
182 |
+
return self::$_config;
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Non-static getter for UI
|
187 |
+
* @return Mage_Connect_Frontend
|
188 |
+
*/
|
189 |
+
public function ui()
|
190 |
+
{
|
191 |
+
return self::$_frontend;
|
192 |
+
}
|
193 |
+
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Get validator object
|
197 |
+
* @return Mage_Connect_Validator
|
198 |
+
*/
|
199 |
+
public function validator()
|
200 |
+
{
|
201 |
+
if(is_null(self::$_validator)) {
|
202 |
+
self::$_validator = new Mage_Connect_Validator();
|
203 |
+
}
|
204 |
+
return self::$_validator;
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Get rest object
|
209 |
+
* @return Mage_Connect_Rest
|
210 |
+
*/
|
211 |
+
public function rest()
|
212 |
+
{
|
213 |
+
if(is_null(self::$_rest)) {
|
214 |
+
self::$_rest = new Mage_Connect_Rest(self::config()->protocol);
|
215 |
+
}
|
216 |
+
return self::$_rest;
|
217 |
+
}
|
218 |
+
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Get commands list sorted
|
222 |
+
* @return array
|
223 |
+
*/
|
224 |
+
public static function getCommands()
|
225 |
+
{
|
226 |
+
if(!count(self::$_commandsAll)) {
|
227 |
+
self::registerCommands();
|
228 |
+
}
|
229 |
+
ksort(self::$_commandsAll);
|
230 |
+
return self::$_commandsAll;
|
231 |
+
}
|
232 |
+
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Get Getopt args from command definitions
|
236 |
+
* and parse them
|
237 |
+
* @param $command
|
238 |
+
* @return array
|
239 |
+
*/
|
240 |
+
public static function getGetoptArgs($command)
|
241 |
+
{
|
242 |
+
$commandInfo = self::commandInfo($command);
|
243 |
+
$short_args = '';
|
244 |
+
$long_args = array();
|
245 |
+
if (empty($commandInfo) || empty($commandInfo['options'])) {
|
246 |
+
return;
|
247 |
+
}
|
248 |
+
reset($commandInfo['options']);
|
249 |
+
while (list($option, $info) = each($commandInfo['options'])) {
|
250 |
+
$larg = $sarg = '';
|
251 |
+
if (isset($info['arg'])) {
|
252 |
+
if ($info['arg']{0} == '(') {
|
253 |
+
$larg = '==';
|
254 |
+
$sarg = '::';
|
255 |
+
$arg = substr($info['arg'], 1, -1);
|
256 |
+
} else {
|
257 |
+
$larg = '=';
|
258 |
+
$sarg = ':';
|
259 |
+
$arg = $info['arg'];
|
260 |
+
}
|
261 |
+
}
|
262 |
+
if (isset($info['shortopt'])) {
|
263 |
+
$short_args .= $info['shortopt'] . $sarg;
|
264 |
+
}
|
265 |
+
$long_args[] = $option . $larg;
|
266 |
+
}
|
267 |
+
return array($short_args, $long_args);
|
268 |
+
}
|
269 |
+
|
270 |
+
/**
|
271 |
+
* Try to register commands automatically
|
272 |
+
* @return void
|
273 |
+
*/
|
274 |
+
public static function registerCommands()
|
275 |
+
{
|
276 |
+
$pathCommands = dirname(__FILE__).DIRECTORY_SEPARATOR.basename(__FILE__, ".php");
|
277 |
+
$f = new DirectoryIterator($pathCommands);
|
278 |
+
foreach($f as $file) {
|
279 |
+
if (! $file->isFile()) {
|
280 |
+
continue;
|
281 |
+
}
|
282 |
+
$pattern = preg_match("/(.*)_Header\.php/imsu", $file->getFilename(), $matches);
|
283 |
+
if(! $pattern) {
|
284 |
+
continue;
|
285 |
+
}
|
286 |
+
include($file->getPathname());
|
287 |
+
if(! isset($commands)) {
|
288 |
+
continue;
|
289 |
+
}
|
290 |
+
$class = __CLASS__."_".$matches[1];
|
291 |
+
foreach ($commands as $k=>$v) {
|
292 |
+
$commands[$k]['class'] = $class;
|
293 |
+
self::$_commandsAll[$k] = $commands[$k];
|
294 |
+
}
|
295 |
+
self::$_commandsByClass[$class] = $commands;
|
296 |
+
}
|
297 |
+
}
|
298 |
+
|
299 |
+
public function doError($command, $message)
|
300 |
+
{
|
301 |
+
return $this->ui()->doError($command, $message);
|
302 |
+
}
|
303 |
+
|
304 |
+
|
305 |
+
/**
|
306 |
+
* Set command return
|
307 |
+
* @param string $key
|
308 |
+
* @param mixed $val
|
309 |
+
* @return void
|
310 |
+
*/
|
311 |
+
public static function setReturn($key, $val)
|
312 |
+
{
|
313 |
+
self::$_return[$key] = $val;
|
314 |
+
}
|
315 |
+
|
316 |
+
/**
|
317 |
+
* Get command return
|
318 |
+
* @param $key
|
319 |
+
* @param $clear
|
320 |
+
* @return mixed
|
321 |
+
*/
|
322 |
+
public static function getReturn($key, $clear = true)
|
323 |
+
{
|
324 |
+
if(isset(self::$_return[$key])) {
|
325 |
+
$out = self::$_return[$key];
|
326 |
+
if($clear) {
|
327 |
+
unset(self::$_return[$key]);
|
328 |
+
}
|
329 |
+
return $out;
|
330 |
+
}
|
331 |
+
return null;
|
332 |
+
}
|
333 |
+
|
334 |
+
/**
|
335 |
+
* Cleanup command params from empty strings
|
336 |
+
*
|
337 |
+
* @param array $params by reference
|
338 |
+
*/
|
339 |
+
public function cleanupParams(array & $params)
|
340 |
+
{
|
341 |
+
$newParams = array();
|
342 |
+
if(!count($params)) {
|
343 |
+
return;
|
344 |
+
}
|
345 |
+
foreach($params as $k=>$v) {
|
346 |
+
if(is_string($v)) {
|
347 |
+
$v = trim($v);
|
348 |
+
if(!strlen($v)) {
|
349 |
+
continue;
|
350 |
+
}
|
351 |
+
}
|
352 |
+
$newParams[] = $v;
|
353 |
+
}
|
354 |
+
$params = $newParams;
|
355 |
+
}
|
356 |
+
|
357 |
+
/**
|
358 |
+
* Splits first command argument: channel/package
|
359 |
+
* to two arguments if found in top of array
|
360 |
+
*
|
361 |
+
* @param array $params
|
362 |
+
*/
|
363 |
+
public function splitPackageArgs(array & $params)
|
364 |
+
{
|
365 |
+
if(!count($params) || !isset($params[0])) {
|
366 |
+
return;
|
367 |
+
}
|
368 |
+
if($this->validator()->validateUrl($params[0])) {
|
369 |
+
return;
|
370 |
+
}
|
371 |
+
if(preg_match("@([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)@ims", $params[0], $subs)) {
|
372 |
+
$params[0] = $subs[2];
|
373 |
+
array_unshift($params, $subs[1]);
|
374 |
+
}
|
375 |
+
}
|
376 |
+
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Get packager instance
|
380 |
+
* @return Mage_Connect_Pacakger
|
381 |
+
*/
|
382 |
+
public function getPackager()
|
383 |
+
{
|
384 |
+
if(!self::$_packager) {
|
385 |
+
self::$_packager = new Mage_Connect_Packager();
|
386 |
+
}
|
387 |
+
return self::$_packager;
|
388 |
+
}
|
389 |
+
|
390 |
+
}
|
lib/Mage/Connect/Command/Channels.php
ADDED
@@ -0,0 +1,189 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
final class Mage_Connect_Command_Channels
|
28 |
+
extends Mage_Connect_Command
|
29 |
+
{
|
30 |
+
|
31 |
+
/**
|
32 |
+
* List available channels
|
33 |
+
* @param $command
|
34 |
+
* @param $params
|
35 |
+
* @param $options
|
36 |
+
*/
|
37 |
+
public function doList($command, $options, $params)
|
38 |
+
{
|
39 |
+
|
40 |
+
try {
|
41 |
+
$title = "Available channels:";
|
42 |
+
$aliasT = "Available aliases:";
|
43 |
+
$packager = $this->getPackager();
|
44 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
45 |
+
if($ftp) {
|
46 |
+
list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
|
47 |
+
$data = $cache->getData();
|
48 |
+
@unlink($config->getFilename());
|
49 |
+
@unlink($cache->getFilename());
|
50 |
+
} else {
|
51 |
+
$cache = $this->getSconfig();
|
52 |
+
$config = $this->config();
|
53 |
+
$data = $cache->getData();
|
54 |
+
}
|
55 |
+
$out = array($command => array('data'=>$data, 'title'=>$title, 'title_aliases'=>$aliasT));
|
56 |
+
$this->ui()->output($out);
|
57 |
+
} catch (Exception $e) {
|
58 |
+
$this->doError($command, $e->getMessage());
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* channel-delete callback method
|
64 |
+
* @param string $command
|
65 |
+
* @param array $options
|
66 |
+
* @param array $params
|
67 |
+
*/
|
68 |
+
public function doDelete($command, $options, $params)
|
69 |
+
{
|
70 |
+
$this->cleanupParams($params);
|
71 |
+
try {
|
72 |
+
if(count($params) != 1) {
|
73 |
+
throw new Exception("Parameters count should be equal to 1");
|
74 |
+
}
|
75 |
+
$packager = $this->getPackager();
|
76 |
+
|
77 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
78 |
+
if($ftp) {
|
79 |
+
list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
|
80 |
+
$cache->deleteChannel($params[0]);
|
81 |
+
$packager->writeToRemoteCache($cache, $ftpObj);
|
82 |
+
@unlink($config->getFilename());
|
83 |
+
} else {
|
84 |
+
$config = $this->config();
|
85 |
+
$cache = $this->getSconfig();
|
86 |
+
$cache->deleteChannel($params[0]);
|
87 |
+
}
|
88 |
+
$this->ui()->output("Successfully deleted");
|
89 |
+
|
90 |
+
} catch (Exception $e) {
|
91 |
+
$this->doError($command, $e->getMessage());
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Channel-add callback
|
97 |
+
* @param string $command
|
98 |
+
* @param array $options
|
99 |
+
* @param array $params
|
100 |
+
*/
|
101 |
+
public function doAdd($command, $options, $params)
|
102 |
+
{
|
103 |
+
$this->cleanupParams($params);
|
104 |
+
try {
|
105 |
+
if(count($params) != 1) {
|
106 |
+
throw new Exception("Parameters count should be equal to 1");
|
107 |
+
}
|
108 |
+
$url = $params[0];
|
109 |
+
$rest = $this->rest();
|
110 |
+
$rest->setChannel($url);
|
111 |
+
$data = $rest->getChannelInfo();
|
112 |
+
$data->url = $url;
|
113 |
+
|
114 |
+
$packager = $this->getPackager();
|
115 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
116 |
+
if($ftp) {
|
117 |
+
list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
|
118 |
+
$cache->addChannel($data->name, $url);
|
119 |
+
$packager->writeToRemoteCache($cache, $ftpObj);
|
120 |
+
@unlink($config->getFilename());
|
121 |
+
} else {
|
122 |
+
$cache = $this->getSconfig();
|
123 |
+
$config = $this->config();
|
124 |
+
$cache->addChannel($data->name, $url);
|
125 |
+
}
|
126 |
+
|
127 |
+
$this->ui()->output("Successfully added: ".$url);
|
128 |
+
} catch (Exception $e) {
|
129 |
+
$this->doError($command, $e->getMessage());
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Get information about given channel callback
|
135 |
+
* @param string $command
|
136 |
+
* @param array $options
|
137 |
+
* @param array $params
|
138 |
+
*/
|
139 |
+
public function doInfo($command, $options, $params)
|
140 |
+
{
|
141 |
+
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* channel-alias
|
146 |
+
* @param $command
|
147 |
+
* @param $options
|
148 |
+
* @param $params
|
149 |
+
* @return unknown_type
|
150 |
+
*/
|
151 |
+
public function doAlias($command, $options, $params)
|
152 |
+
{
|
153 |
+
$this->cleanupParams($params);
|
154 |
+
try {
|
155 |
+
if(count($params) != 2) {
|
156 |
+
throw new Exception("Parameters count should be equal to 2");
|
157 |
+
}
|
158 |
+
|
159 |
+
$packager = $this->getPackager();
|
160 |
+
$chanUrl = $params[0];
|
161 |
+
$alias = $params[1];
|
162 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
163 |
+
if($ftp) {
|
164 |
+
list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
|
165 |
+
$cache->addChannelAlias($chanUrl, $alias);
|
166 |
+
$packager->writeToRemoteCache($cache, $ftpObj);
|
167 |
+
@unlink($config->getFilename());
|
168 |
+
} else {
|
169 |
+
$cache = $this->getSconfig();
|
170 |
+
$config = $this->config();
|
171 |
+
$cache->addChannelAlias($chanUrl, $alias);
|
172 |
+
}
|
173 |
+
$this->ui()->output("Successfully added: ".$alias);
|
174 |
+
} catch (Exception $e) {
|
175 |
+
$this->doError($command, $e->getMessage());
|
176 |
+
}
|
177 |
+
}
|
178 |
+
|
179 |
+
public function doLogin($command, $options, $params)
|
180 |
+
{
|
181 |
+
|
182 |
+
}
|
183 |
+
|
184 |
+
public function doLogout($command, $options, $params)
|
185 |
+
{
|
186 |
+
|
187 |
+
}
|
188 |
+
|
189 |
+
}
|
lib/Mage/Connect/Command/Channels_Header.php
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
$commands = array(
|
28 |
+
'list-channels' => array(
|
29 |
+
'summary' => 'List Available Channels',
|
30 |
+
'function' => 'doList',
|
31 |
+
'shortcut' => 'lc',
|
32 |
+
'options' => array(),
|
33 |
+
'doc' => '
|
34 |
+
List all available channels for installation.
|
35 |
+
',
|
36 |
+
),
|
37 |
+
'channel-delete' => array(
|
38 |
+
'summary' => 'Remove a Channel From the List',
|
39 |
+
'function' => 'doDelete',
|
40 |
+
'shortcut' => 'cde',
|
41 |
+
'options' => array(),
|
42 |
+
'doc' => '<channel name>
|
43 |
+
Delete a channel from the registry. You may not
|
44 |
+
remove any channel that has installed packages.
|
45 |
+
'
|
46 |
+
),
|
47 |
+
'channel-add' => array(
|
48 |
+
'summary' => 'Add a Channel',
|
49 |
+
'function' => 'doAdd',
|
50 |
+
'shortcut' => 'ca',
|
51 |
+
'options' => array(),
|
52 |
+
'doc' => '<channel.xml>
|
53 |
+
Add a private channel to the channel list. Note that all
|
54 |
+
public channels should be synced using "update-channels".
|
55 |
+
Parameter may be either a local file or remote URL to a
|
56 |
+
channel.xml.
|
57 |
+
'
|
58 |
+
),
|
59 |
+
'channel-info' => array(
|
60 |
+
'summary' => 'Retrieve Information on a Channel',
|
61 |
+
'function' => 'doInfo',
|
62 |
+
'shortcut' => 'ci',
|
63 |
+
'options' => array(),
|
64 |
+
'doc' => '<package>
|
65 |
+
List the files in an installed package.
|
66 |
+
'
|
67 |
+
),
|
68 |
+
'channel-alias' => array(
|
69 |
+
'summary' => 'Specify an alias to a channel name',
|
70 |
+
'function' => 'doAlias',
|
71 |
+
'shortcut' => 'cha',
|
72 |
+
'options' => array(),
|
73 |
+
'doc' => '<channel> <alias>
|
74 |
+
Specify a specific alias to use for a channel name.
|
75 |
+
The alias may not be an existing channel name or
|
76 |
+
alias.
|
77 |
+
'
|
78 |
+
),
|
79 |
+
'channel-login' => array(
|
80 |
+
'summary' => 'Connects and authenticates to remote channel server',
|
81 |
+
'shortcut' => 'cli',
|
82 |
+
'function' => 'doLogin',
|
83 |
+
'options' => array(),
|
84 |
+
'doc' => '<channel name>
|
85 |
+
Log in to a remote channel server. If <channel name> is not supplied,
|
86 |
+
the default channel is used. To use remote functions in the installer
|
87 |
+
that require any kind of privileges, you need to log in first. The
|
88 |
+
username and password you enter here will be stored in your per-user
|
89 |
+
PEAR configuration (~/.pearrc on Unix-like systems). After logging
|
90 |
+
in, your username and password will be sent along in subsequent
|
91 |
+
operations on the remote server.',
|
92 |
+
),
|
93 |
+
'channel-logout' => array(
|
94 |
+
'summary' => 'Logs out from the remote channel server',
|
95 |
+
'shortcut' => 'clo',
|
96 |
+
'function' => 'doLogout',
|
97 |
+
'options' => array(),
|
98 |
+
'doc' => '<channel name>
|
99 |
+
Logs out from a remote channel server. If <channel name> is not supplied,
|
100 |
+
the default channel is used. This command does not actually connect to the
|
101 |
+
remote server, it only deletes the stored username and password from your user
|
102 |
+
configuration.',
|
103 |
+
),
|
104 |
+
);
|
105 |
+
|
lib/Mage/Connect/Command/Config.php
ADDED
@@ -0,0 +1,211 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
|
28 |
+
class Mage_Connect_Command_Config
|
29 |
+
extends Mage_Connect_Command
|
30 |
+
|
31 |
+
{
|
32 |
+
const PARAM_KEY = 0;
|
33 |
+
const PARAM_VAL = 1;
|
34 |
+
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Show config variable
|
38 |
+
* @param string $command
|
39 |
+
* @param array $options
|
40 |
+
* @param array $params
|
41 |
+
* @return void
|
42 |
+
*/
|
43 |
+
public function doConfigShow($command, $options, $params)
|
44 |
+
{
|
45 |
+
$this->cleanupParams($params);
|
46 |
+
|
47 |
+
try {
|
48 |
+
$values = array();
|
49 |
+
|
50 |
+
$packager = $this->getPackager();
|
51 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
52 |
+
if($ftp) {
|
53 |
+
list($config, $ftpObj) = $packager->getRemoteConfig($ftp);
|
54 |
+
} else {
|
55 |
+
$config = $this->config();
|
56 |
+
}
|
57 |
+
foreach( $config as $k=>$v ) {
|
58 |
+
$values[$k] = $v;
|
59 |
+
}
|
60 |
+
if($ftp) {
|
61 |
+
@unlink($config->getFilename());
|
62 |
+
}
|
63 |
+
$data = array($command => array('data'=>$values));
|
64 |
+
$this->ui()->output($data);
|
65 |
+
} catch (Exception $e) {
|
66 |
+
if($ftp) {
|
67 |
+
@unlink($config->getFilename());
|
68 |
+
}
|
69 |
+
return $this->doError($command, $e->getMessage());
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Set config variable
|
76 |
+
* @param string $command
|
77 |
+
* @param array $options
|
78 |
+
* @param array $params
|
79 |
+
* @return void
|
80 |
+
*/
|
81 |
+
public function doConfigSet($command, $options, $params)
|
82 |
+
{
|
83 |
+
$this->cleanupParams($params);
|
84 |
+
|
85 |
+
try {
|
86 |
+
if(count($params) < 2) {
|
87 |
+
throw new Exception("Parameters count should be >= 2");
|
88 |
+
}
|
89 |
+
$key = strtolower($params[self::PARAM_KEY]);
|
90 |
+
$val = strval($params[self::PARAM_VAL]);
|
91 |
+
$packager = $this->getPackager();
|
92 |
+
|
93 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
94 |
+
if($ftp) {
|
95 |
+
list($config, $ftpObj) = $packager->getRemoteConfig($ftp);
|
96 |
+
} else {
|
97 |
+
$config = $this->config();
|
98 |
+
}
|
99 |
+
|
100 |
+
if(!$config->hasKey($key)) {
|
101 |
+
throw new Exception ("No such config variable: {$key}!");
|
102 |
+
}
|
103 |
+
if(!$config->validate($key, $val)) {
|
104 |
+
$possible = $this->config()->possible($key);
|
105 |
+
$type = $this->config()->type($key);
|
106 |
+
$errString = "Invalid value specified for $key!";
|
107 |
+
throw new Exception($errString);
|
108 |
+
}
|
109 |
+
if($ftp) {
|
110 |
+
$packager->writeToRemoteConfig($config, $ftpObj);
|
111 |
+
}
|
112 |
+
$this->config()->$key = $val;
|
113 |
+
$this->ui()->output('Success');
|
114 |
+
} catch (Exception $e) {
|
115 |
+
if($ftp) {
|
116 |
+
@unlink($config->getFilename());
|
117 |
+
}
|
118 |
+
return $this->doError($command, $e->getMessage());
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Get config var
|
124 |
+
* @param string $command
|
125 |
+
* @param array $options
|
126 |
+
* @param array $params
|
127 |
+
* @return void
|
128 |
+
*/
|
129 |
+
public function doConfigGet($command, $options, $params)
|
130 |
+
{
|
131 |
+
$this->cleanupParams($params);
|
132 |
+
|
133 |
+
try {
|
134 |
+
if(count($params) < 1) {
|
135 |
+
throw new Exception("Parameters count should be >= 1");
|
136 |
+
}
|
137 |
+
$packager = $this->getPackager();
|
138 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
139 |
+
if($ftp) {
|
140 |
+
list($config, $ftpObj) = $packager->getRemoteConfig($ftp);
|
141 |
+
} else {
|
142 |
+
$config = $this->config();
|
143 |
+
}
|
144 |
+
$key = strtolower($params[self::PARAM_KEY]);
|
145 |
+
if(!$config->hasKey($key)) {
|
146 |
+
throw new Exception("No such config variable '{$key}'!");
|
147 |
+
}
|
148 |
+
if($ftp) {
|
149 |
+
@unlink($config->getFilename());
|
150 |
+
}
|
151 |
+
$this->ui()->output($config->$key);
|
152 |
+
} catch (Exception $e) {
|
153 |
+
if($ftp) {
|
154 |
+
@unlink($config->getFilename());
|
155 |
+
}
|
156 |
+
return $this->doError($command, $e->getMessage());
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Config help
|
162 |
+
* @param string $command
|
163 |
+
* @param array $options
|
164 |
+
* @param array $params
|
165 |
+
* @return void
|
166 |
+
*/
|
167 |
+
public function doConfigHelp($command, $options, $params)
|
168 |
+
{
|
169 |
+
try {
|
170 |
+
$this->cleanupParams($params);
|
171 |
+
if(count($params) < 1) {
|
172 |
+
throw new Exception( "Parameters count should be >= 1");
|
173 |
+
}
|
174 |
+
$packager = $this->getPackager();
|
175 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
176 |
+
if($ftp) {
|
177 |
+
list($config, $ftpObj) = $packager->getRemoteConfig($ftp);
|
178 |
+
} else {
|
179 |
+
$config = $this->config();
|
180 |
+
}
|
181 |
+
|
182 |
+
$key = strtolower($params[self::PARAM_KEY]);
|
183 |
+
if(!$this->config()->hasKey($key)) {
|
184 |
+
throw new Exception("No such config variable '{$key}'!");
|
185 |
+
}
|
186 |
+
|
187 |
+
$possible = $config->possible($key);
|
188 |
+
$type = $config->type($key);
|
189 |
+
$doc = $config->doc($key);
|
190 |
+
if($ftp) {
|
191 |
+
@unlink($config->getFilename());
|
192 |
+
}
|
193 |
+
$data = array();
|
194 |
+
$data[$command]['data'] = array(
|
195 |
+
'name' => array('Variable name', $key),
|
196 |
+
'type' => array('Value type', $type),
|
197 |
+
'possible' => array('Possible values', $possible),
|
198 |
+
'doc' => $doc,
|
199 |
+
);
|
200 |
+
$this->ui()->output($data);
|
201 |
+
} catch (Exception $e) {
|
202 |
+
if($ftp) {
|
203 |
+
@unlink($config->getFilename());
|
204 |
+
}
|
205 |
+
return $this->doError($command, $e->getMessage());
|
206 |
+
}
|
207 |
+
}
|
208 |
+
|
209 |
+
}
|
210 |
+
|
211 |
+
|
lib/Mage/Connect/Command/Config_Header.php
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
$commands = array(
|
28 |
+
'config-show' => array(
|
29 |
+
'summary' => 'Show All Settings',
|
30 |
+
'function' => 'doConfigShow',
|
31 |
+
'shortcut' => 'csh',
|
32 |
+
'options' => array(
|
33 |
+
'channel' => array(
|
34 |
+
'shortopt' => 'c',
|
35 |
+
'doc' => 'show configuration variables for another channel',
|
36 |
+
'arg' => 'CHAN',
|
37 |
+
),
|
38 |
+
),
|
39 |
+
'doc' => '[layer]
|
40 |
+
Displays all configuration values. An optional argument
|
41 |
+
may be used to tell which configuration layer to display. Valid
|
42 |
+
configuration layers are "user", "system" and "default". To display
|
43 |
+
configurations for different channels, set the default_channel
|
44 |
+
configuration variable and run config-show again.
|
45 |
+
',
|
46 |
+
),
|
47 |
+
'config-get' => array(
|
48 |
+
'summary' => 'Show One Setting',
|
49 |
+
'function' => 'doConfigGet',
|
50 |
+
'shortcut' => 'cg',
|
51 |
+
'options' => array(
|
52 |
+
'channel' => array(
|
53 |
+
'shortopt' => 'c',
|
54 |
+
'doc' => 'show configuration variables for another channel',
|
55 |
+
'arg' => 'CHAN',
|
56 |
+
),
|
57 |
+
),
|
58 |
+
'doc' => '<parameter> [layer]
|
59 |
+
Displays the value of one configuration parameter. The
|
60 |
+
first argument is the name of the parameter, an optional second argument
|
61 |
+
may be used to tell which configuration layer to look in. Valid configuration
|
62 |
+
layers are "user", "system" and "default". If no layer is specified, a value
|
63 |
+
will be picked from the first layer that defines the parameter, in the order
|
64 |
+
just specified. The configuration value will be retrieved for the channel
|
65 |
+
specified by the default_channel configuration variable.
|
66 |
+
',
|
67 |
+
),
|
68 |
+
'config-set' => array(
|
69 |
+
'summary' => 'Change Setting',
|
70 |
+
'function' => 'doConfigSet',
|
71 |
+
'shortcut' => 'cs',
|
72 |
+
'options' => array(
|
73 |
+
'channel' => array(
|
74 |
+
'shortopt' => 'c',
|
75 |
+
'doc' => 'show configuration variables for another channel',
|
76 |
+
'arg' => 'CHAN',
|
77 |
+
),
|
78 |
+
),
|
79 |
+
'doc' => '<parameter> <value> [layer]
|
80 |
+
Sets the value of one configuration parameter. The first argument is
|
81 |
+
the name of the parameter, the second argument is the new value. Some
|
82 |
+
parameters are subject to validation, and the command will fail with
|
83 |
+
an error message if the new value does not make sense. An optional
|
84 |
+
third argument may be used to specify in which layer to set the
|
85 |
+
configuration parameter. The default layer is "user". The
|
86 |
+
configuration value will be set for the current channel, which
|
87 |
+
is controlled by the default_channel configuration variable.
|
88 |
+
',
|
89 |
+
),
|
90 |
+
'config-help' => array(
|
91 |
+
'summary' => 'Show Information About Setting',
|
92 |
+
'function' => 'doConfigHelp',
|
93 |
+
'shortcut' => 'ch',
|
94 |
+
'options' => array(),
|
95 |
+
'doc' => '[parameter]
|
96 |
+
Displays help for a configuration parameter. Without arguments it
|
97 |
+
displays help for all configuration parameters.
|
98 |
+
',
|
99 |
+
),
|
100 |
+
);
|
lib/Mage/Connect/Command/Install.php
ADDED
@@ -0,0 +1,448 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
|
28 |
+
final class Mage_Connect_Command_Install
|
29 |
+
extends Mage_Connect_Command
|
30 |
+
{
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Install action callback
|
34 |
+
* @param string $command
|
35 |
+
* @param array $options
|
36 |
+
* @param array $params
|
37 |
+
* @return void
|
38 |
+
*/
|
39 |
+
public function doInstall($command, $options, $params, $objects = array())
|
40 |
+
{
|
41 |
+
$this->cleanupParams($params);
|
42 |
+
|
43 |
+
$installFileMode = $command === 'install-file';
|
44 |
+
|
45 |
+
|
46 |
+
|
47 |
+
|
48 |
+
try {
|
49 |
+
$packager = $this->getPackager();
|
50 |
+
$forceMode = isset($options['force']);
|
51 |
+
$upgradeAllMode = $command == 'upgrade-all';
|
52 |
+
$upgradeMode = $command == 'upgrade' || $command == 'upgrade-all';
|
53 |
+
$noFilesInstall = isset($options['nofiles']);
|
54 |
+
$withDepsMode = !isset($options['nodeps']);
|
55 |
+
$ignoreModifiedMode = true || !isset($options['ignorelocalmodification']);
|
56 |
+
|
57 |
+
$rest = $this->rest();
|
58 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
59 |
+
if($ftp) {
|
60 |
+
list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
|
61 |
+
} else {
|
62 |
+
$config = $this->config();
|
63 |
+
$cache = $this->getSconfig();
|
64 |
+
}
|
65 |
+
if($installFileMode) {
|
66 |
+
if(count($params) < 1) {
|
67 |
+
throw new Exception("Argument should be: filename");
|
68 |
+
}
|
69 |
+
$filename = $params[0];
|
70 |
+
if(!@file_exists($filename)) {
|
71 |
+
throw new Exception("File '{$filename}' not found");
|
72 |
+
}
|
73 |
+
if(!@is_readable($filename)) {
|
74 |
+
throw new Exception("File '{$filename}' is not readable");
|
75 |
+
}
|
76 |
+
|
77 |
+
$package = new Mage_Connect_Package($filename);
|
78 |
+
$package->validate();
|
79 |
+
$errors = $package->getErrors();
|
80 |
+
if(count($errors)) {
|
81 |
+
throw new Exception("Package file is invalid\n".implode("\n", $errors));
|
82 |
+
}
|
83 |
+
|
84 |
+
$pChan = $package->getChannel();
|
85 |
+
$pName = $package->getName();
|
86 |
+
$pVer = $package->getVersion();
|
87 |
+
|
88 |
+
|
89 |
+
if(!$cache->isChannel($pChan)) {
|
90 |
+
throw new Exception("'{$pChan}' is not installed channel");
|
91 |
+
}
|
92 |
+
|
93 |
+
$conflicts = $cache->hasConflicts($pChan, $pName, $pVer);
|
94 |
+
|
95 |
+
if(false !== $conflicts) {
|
96 |
+
$conflicts = implode(", ",$conflicts);
|
97 |
+
if($forceMode) {
|
98 |
+
$this->doError($command, "Package {$pChan}/{$pName} {$pVer} conflicts with: ".$conflicts);
|
99 |
+
} else {
|
100 |
+
throw new Exception("Package {$pChan}/{$pName} {$pVer} conflicts with: ".$conflicts);
|
101 |
+
}
|
102 |
+
}
|
103 |
+
|
104 |
+
$conflicts = $package->checkPhpDependencies();
|
105 |
+
if(true !== $conflicts) {
|
106 |
+
$confilcts = implode(",",$conflicts);
|
107 |
+
$err = "Package {$pChan}/{$pName} {$pVer} depends on PHP extensions: ".$conflicts;
|
108 |
+
if($forceMode) {
|
109 |
+
$this->doError($command, $err);
|
110 |
+
} else {
|
111 |
+
throw new Exception($err);
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
$conflicts = $package->checkPhpVersion();
|
116 |
+
if(true !== $conflicts) {
|
117 |
+
$err = "Package {$pChan}/{$pName} {$pVer}: ".$conflicts;
|
118 |
+
if($forceMode) {
|
119 |
+
$this->doError($command, $err);
|
120 |
+
} else {
|
121 |
+
throw new Exception($err);
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
|
126 |
+
if(!$noFilesInstall) {
|
127 |
+
if($ftp) {
|
128 |
+
$packager->processInstallPackageFtp($package, $filename, $config, $ftpObj);
|
129 |
+
} else {
|
130 |
+
$packager->processInstallPackage($package, $filename, $config);
|
131 |
+
}
|
132 |
+
}
|
133 |
+
$cache->addPackage($package);
|
134 |
+
$installedDeps = array();
|
135 |
+
$installedDepsAssoc = array();
|
136 |
+
$installedDepsAssoc[] = array('channel'=>$pChan, 'name'=>$pName, 'version'=>$pVer);
|
137 |
+
$installedDeps[] = array($pChan, $pName, $pVer);
|
138 |
+
|
139 |
+
|
140 |
+
$title = isset($options['title']) ? $options['title'] : "Package installed: ";
|
141 |
+
$out = array($command => array('data'=>$installedDeps, 'assoc'=>$installedDepsAssoc, 'title'=>$title));
|
142 |
+
|
143 |
+
if($ftp) {
|
144 |
+
$packager->writeToRemoteCache($cache, $ftpObj);
|
145 |
+
@unlink($config->getFilename());
|
146 |
+
}
|
147 |
+
|
148 |
+
$this->ui()->output($out);
|
149 |
+
return $out[$command]['data'];
|
150 |
+
}
|
151 |
+
|
152 |
+
if(!$upgradeAllMode) {
|
153 |
+
|
154 |
+
if(count($params) < 2) {
|
155 |
+
throw new Exception("Argument should be: channelName packageName");
|
156 |
+
}
|
157 |
+
$channel = $params[0];
|
158 |
+
$package = $params[1];
|
159 |
+
$argVersionMax = isset($params[2]) ? $params[2]: false;
|
160 |
+
$argVersionMin = false;
|
161 |
+
|
162 |
+
if($cache->isChannelName($channel)) {
|
163 |
+
$uri = $cache->chanUrl($channel);
|
164 |
+
} elseif($this->validator()->validateUrl($channel)) {
|
165 |
+
$uri = $channel;
|
166 |
+
} elseif($channel) {
|
167 |
+
$uri = $config->protocol.'://'.$channel;
|
168 |
+
} else {
|
169 |
+
throw new Exception("'{$channel}' is not existant channel name / valid uri");
|
170 |
+
}
|
171 |
+
|
172 |
+
if($uri && !$cache->isChannel($uri)) {
|
173 |
+
$rest->setChannel($uri);
|
174 |
+
$data = $rest->getChannelInfo();
|
175 |
+
$data->uri = $uri;
|
176 |
+
$cache->addChannel($data->name, $uri);
|
177 |
+
$this->ui()->output("Successfully added channel: ".$uri);
|
178 |
+
}
|
179 |
+
$channelName = $cache->chanName($channel);
|
180 |
+
//var_dump($channelName);
|
181 |
+
$packagesToInstall = $packager->getDependenciesList( $channelName, $package, $cache, $config, $argVersionMax, $argVersionMin, $withDepsMode);
|
182 |
+
$packagesToInstall = $packagesToInstall['result'];
|
183 |
+
//var_dump($packagesToInstall);
|
184 |
+
|
185 |
+
} else {
|
186 |
+
if(empty($params[0])) {
|
187 |
+
$channels = $cache->getChannelNames();
|
188 |
+
} else {
|
189 |
+
$channel = $params[0];
|
190 |
+
if(!$cache->isChannel($channel)) {
|
191 |
+
throw new Exception("'{$channel}' is not existant channel name / valid uri");
|
192 |
+
}
|
193 |
+
$channels = $cache->chanName($channel);
|
194 |
+
}
|
195 |
+
$packagesToInstall = array();
|
196 |
+
$neededToUpgrade = $packager->getUpgradesList($channels, $cache, $config);
|
197 |
+
foreach($neededToUpgrade as $chan=>$packages) {
|
198 |
+
foreach($packages as $name=>$data) {
|
199 |
+
$versionTo = $data['to'];
|
200 |
+
$tmp = $packager->getDependenciesList( $chan, $name, $cache, $config, $versionTo, $versionTo, $withDepsMode);
|
201 |
+
if(count($tmp['result'])) {
|
202 |
+
$packagesToInstall = array_merge($packagesToInstall, $tmp['result']);
|
203 |
+
}
|
204 |
+
}
|
205 |
+
}
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Make installation
|
210 |
+
*/
|
211 |
+
$installedDeps = array();
|
212 |
+
$installedDepsAssoc = array();
|
213 |
+
$keys = array();
|
214 |
+
|
215 |
+
foreach($packagesToInstall as $package) {
|
216 |
+
try {
|
217 |
+
$pName = $package['name'];
|
218 |
+
$pChan = $package['channel'];
|
219 |
+
$pVer = $package['downloaded_version'];
|
220 |
+
$rest->setChannel($cache->chanUrl($pChan));
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Upgrade mode
|
224 |
+
*/
|
225 |
+
if($upgradeMode && $cache->hasPackage($pChan, $pName, $pVer, $pVer)) {
|
226 |
+
$this->ui()->output("Already installed: {$pChan}/{$pName} {$pVer}, skipping");
|
227 |
+
continue;
|
228 |
+
}
|
229 |
+
|
230 |
+
$conflicts = $cache->hasConflicts($pChan, $pName, $pVer);
|
231 |
+
|
232 |
+
if(false !== $conflicts) {
|
233 |
+
$conflicts = implode(", ",$conflicts);
|
234 |
+
if($forceMode) {
|
235 |
+
$this->doError($command, "Package {$pChan}/{$pName} {$pVer} conflicts with: ".$conflicts);
|
236 |
+
} else {
|
237 |
+
throw new Exception("Package {$pChan}/{$pName} {$pVer} conflicts with: ".$conflicts);
|
238 |
+
}
|
239 |
+
}
|
240 |
+
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Modifications
|
244 |
+
*/
|
245 |
+
if ($upgradeMode && !$ignoreModifiedMode) {
|
246 |
+
if($ftp) {
|
247 |
+
$modifications = $packager->getRemoteModifiedFiles($pChan, $pName, $cache, $config, $ftp);
|
248 |
+
} else {
|
249 |
+
$modifications = $packager->getLocalModifiedFiles($pChan, $pName, $cache, $config);
|
250 |
+
}
|
251 |
+
if (count($modifications) > 0) {
|
252 |
+
$this->ui()->output('Changed locally: ');
|
253 |
+
foreach ($modifications as $row) {
|
254 |
+
if(!$ftp) {
|
255 |
+
$this->ui()->output($config->magento_root.DS.$row);
|
256 |
+
} else {
|
257 |
+
$this->ui()->output($row);
|
258 |
+
}
|
259 |
+
}
|
260 |
+
/*$this->ui()->confirm('Do you want rewrite all files?');
|
261 |
+
continue;*/
|
262 |
+
}
|
263 |
+
}
|
264 |
+
|
265 |
+
$dir = $config->getChannelCacheDir($pChan);
|
266 |
+
@mkdir($dir, 0777, true);
|
267 |
+
$file = $dir.DIRECTORY_SEPARATOR.$pName."-".$pVer.".tgz";
|
268 |
+
if(!@file_exists($file)) {
|
269 |
+
$rest->downloadPackageFileOfRelease($pName, $pVer, $file);
|
270 |
+
}
|
271 |
+
$package = new Mage_Connect_Package($file);
|
272 |
+
|
273 |
+
|
274 |
+
|
275 |
+
$conflicts = $package->checkPhpDependencies();
|
276 |
+
if(true !== $conflicts) {
|
277 |
+
$confilcts = implode(",",$conflicts);
|
278 |
+
$err = "Package {$pChan}/{$pName} {$pVer} depends on PHP extensions: ".$conflicts;
|
279 |
+
if($forceMode) {
|
280 |
+
$this->doError($command, $err);
|
281 |
+
} else {
|
282 |
+
throw new Exception($err);
|
283 |
+
}
|
284 |
+
}
|
285 |
+
|
286 |
+
$conflicts = $package->checkPhpVersion();
|
287 |
+
if(true !== $conflicts) {
|
288 |
+
$err = "Package {$pChan}/{$pName} {$pVer}: ".$conflicts;
|
289 |
+
if($forceMode) {
|
290 |
+
$this->doError($command, $err);
|
291 |
+
} else {
|
292 |
+
throw new Exception($err);
|
293 |
+
}
|
294 |
+
}
|
295 |
+
|
296 |
+
if(!$noFilesInstall) {
|
297 |
+
if($ftp) {
|
298 |
+
$packager->processInstallPackageFtp($package, $file, $config, $ftpObj);
|
299 |
+
} else {
|
300 |
+
$packager->processInstallPackage($package, $file, $config);
|
301 |
+
}
|
302 |
+
}
|
303 |
+
$cache->addPackage($package);
|
304 |
+
|
305 |
+
$installedDepsAssoc[] = array('channel'=>$pChan, 'name'=>$pName, 'version'=>$pVer);
|
306 |
+
$installedDeps[] = array($pChan, $pName, $pVer);
|
307 |
+
|
308 |
+
} catch(Exception $e) {
|
309 |
+
$this->doError($command, $e->getMessage());
|
310 |
+
}
|
311 |
+
}
|
312 |
+
|
313 |
+
|
314 |
+
|
315 |
+
$title = isset($options['title']) ? $options['title'] : "Package installed: ";
|
316 |
+
$out = array($command => array('data'=>$installedDeps, 'assoc'=>$installedDepsAssoc, 'title'=>$title));
|
317 |
+
|
318 |
+
if($ftp) {
|
319 |
+
$packager->writeToRemoteCache($cache, $ftpObj);
|
320 |
+
@unlink($config->getFilename());
|
321 |
+
}
|
322 |
+
|
323 |
+
$this->ui()->output($out);
|
324 |
+
return $out[$command]['data'];
|
325 |
+
|
326 |
+
} catch (Exception $e) {
|
327 |
+
if($ftp) {
|
328 |
+
$packager->writeToRemoteCache($cache, $ftpObj);
|
329 |
+
@unlink($config->getFilename());
|
330 |
+
}
|
331 |
+
return $this->doError($command, $e->getMessage());
|
332 |
+
}
|
333 |
+
}
|
334 |
+
|
335 |
+
/**
|
336 |
+
* Upgrade action callback
|
337 |
+
* @param string $command
|
338 |
+
* @param array $options
|
339 |
+
* @param array $params
|
340 |
+
* @return void
|
341 |
+
*/
|
342 |
+
public function doUpgrade($command, $options, $params)
|
343 |
+
{
|
344 |
+
$options['title'] = "Package upgraded: ";
|
345 |
+
return $this->doInstall($command, $options, $params);
|
346 |
+
}
|
347 |
+
|
348 |
+
/**
|
349 |
+
* Updgrade action callback
|
350 |
+
* @param string $command
|
351 |
+
* @param array $options
|
352 |
+
* @param array $params
|
353 |
+
* @return void
|
354 |
+
*/
|
355 |
+
public function doUpgradeAll($command, $options, $params)
|
356 |
+
{
|
357 |
+
$options['title'] = "Package upgraded: ";
|
358 |
+
return $this->doInstall($command, $options, $params);
|
359 |
+
}
|
360 |
+
|
361 |
+
/**
|
362 |
+
* Uninstall package callback
|
363 |
+
* @param string $command
|
364 |
+
* @param array $options
|
365 |
+
* @param array $params
|
366 |
+
* @return unknown_type
|
367 |
+
*/
|
368 |
+
public function doUninstall($command, $options, $params)
|
369 |
+
{
|
370 |
+
$this->cleanupParams($params);
|
371 |
+
//$this->splitPackageArgs($params);
|
372 |
+
|
373 |
+
try {
|
374 |
+
if(count($params) != 2) {
|
375 |
+
throw new Exception("Argument count should be = 2");
|
376 |
+
}
|
377 |
+
|
378 |
+
$channel = $params[0];
|
379 |
+
$package = $params[1];
|
380 |
+
$packager = $this->getPackager();
|
381 |
+
$withDepsMode = !isset($options['nodeps']);
|
382 |
+
$forceMode = isset($options['force']);
|
383 |
+
|
384 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
385 |
+
if($ftp) {
|
386 |
+
list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
|
387 |
+
} else {
|
388 |
+
$cache = $this->getSconfig();
|
389 |
+
$config = $this->config();
|
390 |
+
}
|
391 |
+
|
392 |
+
$chan = $cache->getChannel($channel);
|
393 |
+
$channel = $cache->chanName($channel);
|
394 |
+
if(!$cache->hasPackage($channel, $package)) {
|
395 |
+
throw new Exception("Package is not installed");
|
396 |
+
}
|
397 |
+
|
398 |
+
$deletedPackages = array();
|
399 |
+
$list = $packager->getUninstallList($channel, $package, $cache, $config, $withDepsMode);
|
400 |
+
foreach($list['list'] as $packageData) {
|
401 |
+
try {
|
402 |
+
$reqd = $cache->requiredByOtherPackages($packageData['channel'], $packageData['name'], $list['list']);
|
403 |
+
if(count($reqd)) {
|
404 |
+
$errMessage = "{$packageData['channel']}/{$packageData['name']} {$packageData['version']} is required by: ";
|
405 |
+
$t = array();
|
406 |
+
foreach($reqd as $r) {
|
407 |
+
$t[] = $r['channel']."/".$r['name']. " ".$r['version'];
|
408 |
+
}
|
409 |
+
$errMessage .= implode(", ", $t);
|
410 |
+
if($forceMode) {
|
411 |
+
$this->ui()->output("Warning: ".$errMessage);
|
412 |
+
} else {
|
413 |
+
throw new Exception($errMessage);
|
414 |
+
}
|
415 |
+
}
|
416 |
+
|
417 |
+
list($chan, $pack) = array($packageData['channel'], $packageData['name']);
|
418 |
+
if($ftp) {
|
419 |
+
$packager->processUninstallPackageFtp($chan, $pack, $cache, $config, $ftp);
|
420 |
+
} else {
|
421 |
+
$packager->processUninstallPackage($chan, $pack, $cache, $config);
|
422 |
+
}
|
423 |
+
$cache->deletePackage($chan, $pack);
|
424 |
+
$deletedPackages[] = array($chan, $pack);
|
425 |
+
|
426 |
+
} catch(Exception $e) {
|
427 |
+
if($forceMode) {
|
428 |
+
$this->doError($command, $e->getMessage());
|
429 |
+
} else {
|
430 |
+
throw new Exception($e->getMessage());
|
431 |
+
}
|
432 |
+
}
|
433 |
+
}
|
434 |
+
if($ftp) {
|
435 |
+
$packager->writeToRemoteCache($cache, $ftpObj);
|
436 |
+
@unlink($config->getFilename());
|
437 |
+
}
|
438 |
+
$out = array($command=>array('data'=>$deletedPackages, 'title'=>'Package deleted: '));
|
439 |
+
$this->ui()->output($out);
|
440 |
+
|
441 |
+
} catch (Exception $e) {
|
442 |
+
return $this->doError($command, $e->getMessage());
|
443 |
+
}
|
444 |
+
|
445 |
+
}
|
446 |
+
|
447 |
+
}
|
448 |
+
|
lib/Mage/Connect/Command/Install_Header.php
ADDED
@@ -0,0 +1,237 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
$commands = array(
|
28 |
+
|
29 |
+
'install-file' => array(
|
30 |
+
'summary' => 'Install Package Archive File',
|
31 |
+
'function' => 'doInstall',
|
32 |
+
'shortcut' => 'if',
|
33 |
+
'options' => array(),
|
34 |
+
'doc' => '',
|
35 |
+
),
|
36 |
+
'install' => array(
|
37 |
+
'summary' => 'Install Package',
|
38 |
+
'function' => 'doInstall',
|
39 |
+
'shortcut' => 'i',
|
40 |
+
'options' => array(
|
41 |
+
'force' => array(
|
42 |
+
'shortopt' => 'f',
|
43 |
+
'doc' => 'will overwrite newer installed packages',
|
44 |
+
),
|
45 |
+
'loose' => array(
|
46 |
+
'shortopt' => 'l',
|
47 |
+
'doc' => 'do not check for recommended dependency version',
|
48 |
+
),
|
49 |
+
'nodeps' => array(
|
50 |
+
'shortopt' => 'n',
|
51 |
+
'doc' => 'ignore dependencies, install anyway',
|
52 |
+
),
|
53 |
+
'ignore-errors' => array(
|
54 |
+
'doc' => 'force install even if there were errors',
|
55 |
+
),
|
56 |
+
'alldeps' => array(
|
57 |
+
'shortopt' => 'a',
|
58 |
+
'doc' => 'install all required and optional dependencies',
|
59 |
+
),
|
60 |
+
'pretend' => array(
|
61 |
+
'shortopt' => 'p',
|
62 |
+
'doc' => 'Only list the packages that would be downloaded',
|
63 |
+
),
|
64 |
+
'ftp=' => array(
|
65 |
+
'shortopt' => 'r=',
|
66 |
+
'doc' => 'Remote side FTP connect string',
|
67 |
+
),
|
68 |
+
),
|
69 |
+
'doc' => '[channel/]<package> ...
|
70 |
+
Installs one or more PEAR packages. You can specify a package to
|
71 |
+
install in four ways:
|
72 |
+
|
73 |
+
"Package-1.0.tgz" : installs from a local file
|
74 |
+
|
75 |
+
"http://example.com/Package-1.0.tgz" : installs from
|
76 |
+
anywhere on the net.
|
77 |
+
|
78 |
+
"package.xml" : installs the package described in
|
79 |
+
package.xml. Useful for testing, or for wrapping a PEAR package in
|
80 |
+
another package manager such as RPM.
|
81 |
+
|
82 |
+
"Package[-version/state][.tar]" : queries your default channel\'s server
|
83 |
+
({config master_server}) and downloads the newest package with
|
84 |
+
the preferred quality/state ({config preferred_state}).
|
85 |
+
|
86 |
+
To retrieve Package version 1.1, use "Package-1.1," to retrieve
|
87 |
+
Package state beta, use "Package-beta." To retrieve an uncompressed
|
88 |
+
file, append .tar (make sure there is no file by the same name first)
|
89 |
+
|
90 |
+
To download a package from another channel, prefix with the channel name like
|
91 |
+
"channel/Package"
|
92 |
+
|
93 |
+
More than one package may be specified at once. It is ok to mix these
|
94 |
+
four ways of specifying packages.
|
95 |
+
'),
|
96 |
+
'upgrade' => array(
|
97 |
+
'summary' => 'Upgrade Package',
|
98 |
+
'function' => 'doUpgrade',
|
99 |
+
'shortcut' => 'up',
|
100 |
+
'options' => array(
|
101 |
+
'channel' => array(
|
102 |
+
'shortopt' => 'c',
|
103 |
+
'doc' => 'upgrade packages from a specific channel',
|
104 |
+
'arg' => 'CHAN',
|
105 |
+
),
|
106 |
+
'force' => array(
|
107 |
+
'shortopt' => 'f',
|
108 |
+
'doc' => 'overwrite newer installed packages',
|
109 |
+
),
|
110 |
+
'loose' => array(
|
111 |
+
'shortopt' => 'l',
|
112 |
+
'doc' => 'do not check for recommended dependency version',
|
113 |
+
),
|
114 |
+
'nodeps' => array(
|
115 |
+
'shortopt' => 'n',
|
116 |
+
'doc' => 'ignore dependencies, upgrade anyway',
|
117 |
+
),
|
118 |
+
'register-only' => array(
|
119 |
+
'shortopt' => 'r',
|
120 |
+
'doc' => 'do not install files, only register the package as upgraded',
|
121 |
+
),
|
122 |
+
'nobuild' => array(
|
123 |
+
'shortopt' => 'B',
|
124 |
+
'doc' => 'don\'t build C extensions',
|
125 |
+
),
|
126 |
+
'nocompress' => array(
|
127 |
+
'shortopt' => 'Z',
|
128 |
+
'doc' => 'request uncompressed files when downloading',
|
129 |
+
),
|
130 |
+
'installroot' => array(
|
131 |
+
'shortopt' => 'R',
|
132 |
+
'arg' => 'DIR',
|
133 |
+
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
|
134 |
+
),
|
135 |
+
'ignore-errors' => array(
|
136 |
+
'doc' => 'force install even if there were errors',
|
137 |
+
),
|
138 |
+
'alldeps' => array(
|
139 |
+
'shortopt' => 'a',
|
140 |
+
'doc' => 'install all required and optional dependencies',
|
141 |
+
),
|
142 |
+
'onlyreqdeps' => array(
|
143 |
+
'shortopt' => 'o',
|
144 |
+
'doc' => 'install all required dependencies',
|
145 |
+
),
|
146 |
+
'offline' => array(
|
147 |
+
'shortopt' => 'O',
|
148 |
+
'doc' => 'do not attempt to download any urls or contact channels',
|
149 |
+
),
|
150 |
+
'pretend' => array(
|
151 |
+
'shortopt' => 'p',
|
152 |
+
'doc' => 'Only list the packages that would be downloaded',
|
153 |
+
),
|
154 |
+
),
|
155 |
+
'doc' => '<package> ...
|
156 |
+
Upgrades one or more PEAR packages. See documentation for the
|
157 |
+
"install" command for ways to specify a package.
|
158 |
+
|
159 |
+
When upgrading, your package will be updated if the provided new
|
160 |
+
package has a higher version number (use the -f option if you need to
|
161 |
+
upgrade anyway).
|
162 |
+
|
163 |
+
More than one package may be specified at once.
|
164 |
+
'),
|
165 |
+
'upgrade-all' => array(
|
166 |
+
'summary' => 'Upgrade All Packages',
|
167 |
+
'function' => 'doUpgradeAll',
|
168 |
+
'shortcut' => 'ua',
|
169 |
+
'options' => array(
|
170 |
+
'channel' => array(
|
171 |
+
'shortopt' => 'c',
|
172 |
+
'doc' => 'upgrade packages from a specific channel',
|
173 |
+
'arg' => 'CHAN',
|
174 |
+
),
|
175 |
+
'nodeps' => array(
|
176 |
+
'shortopt' => 'n',
|
177 |
+
'doc' => 'ignore dependencies, upgrade anyway',
|
178 |
+
),
|
179 |
+
'register-only' => array(
|
180 |
+
'shortopt' => 'r',
|
181 |
+
'doc' => 'do not install files, only register the package as upgraded',
|
182 |
+
),
|
183 |
+
'nobuild' => array(
|
184 |
+
'shortopt' => 'B',
|
185 |
+
'doc' => 'don\'t build C extensions',
|
186 |
+
),
|
187 |
+
'nocompress' => array(
|
188 |
+
'shortopt' => 'Z',
|
189 |
+
'doc' => 'request uncompressed files when downloading',
|
190 |
+
),
|
191 |
+
'installroot' => array(
|
192 |
+
'shortopt' => 'R',
|
193 |
+
'arg' => 'DIR',
|
194 |
+
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
|
195 |
+
),
|
196 |
+
'ignore-errors' => array(
|
197 |
+
'doc' => 'force install even if there were errors',
|
198 |
+
),
|
199 |
+
'loose' => array(
|
200 |
+
'doc' => 'do not check for recommended dependency version',
|
201 |
+
),
|
202 |
+
),
|
203 |
+
'doc' => '
|
204 |
+
WARNING: This function is deprecated in favor of using the upgrade command with no params
|
205 |
+
|
206 |
+
Upgrades all packages that have a newer release available. Upgrades are
|
207 |
+
done only if there is a release available of the state specified in
|
208 |
+
"preferred_state" (currently {config preferred_state}), or a state considered
|
209 |
+
more stable.
|
210 |
+
'),
|
211 |
+
'uninstall' => array(
|
212 |
+
'summary' => 'Un-install Package',
|
213 |
+
'function' => 'doUninstall',
|
214 |
+
'shortcut' => 'un',
|
215 |
+
'options' => array(
|
216 |
+
'nodeps' => array(
|
217 |
+
'shortopt' => 'n',
|
218 |
+
'doc' => 'ignore dependencies, uninstall anyway',
|
219 |
+
),
|
220 |
+
'register-only' => array(
|
221 |
+
'shortopt' => 'r',
|
222 |
+
'doc' => 'do not remove files, only register the packages as not installed',
|
223 |
+
),
|
224 |
+
'ignore-errors' => array(
|
225 |
+
'doc' => 'force install even if there were errors',
|
226 |
+
),
|
227 |
+
'offline' => array(
|
228 |
+
'shortopt' => 'O',
|
229 |
+
'doc' => 'do not attempt to uninstall remotely',
|
230 |
+
),
|
231 |
+
),
|
232 |
+
'doc' => '[channel/]<package> ...
|
233 |
+
Uninstalls one or more PEAR packages. More than one package may be
|
234 |
+
specified at once. Prefix with channel name to uninstall from a
|
235 |
+
channel not in your default channel ({config default_channel})
|
236 |
+
'),
|
237 |
+
);
|
lib/Mage/Connect/Command/Package.php
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide- web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
final class Mage_Connect_Command_Package
|
28 |
+
extends Mage_Connect_Command
|
29 |
+
{
|
30 |
+
/**
|
31 |
+
* Dependencies list
|
32 |
+
* @var array
|
33 |
+
*/
|
34 |
+
private $_depsList = array();
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Releases list
|
38 |
+
* @var array
|
39 |
+
*/
|
40 |
+
private $_releasesList = array();
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Package command callback
|
44 |
+
* @param string $command
|
45 |
+
* @param array $options
|
46 |
+
* @param array $params
|
47 |
+
* @return void
|
48 |
+
*/
|
49 |
+
public function doPackage($command, $options, $params)
|
50 |
+
{
|
51 |
+
$this->cleanupParams($params);
|
52 |
+
|
53 |
+
if(count($params) < 1) {
|
54 |
+
return $this->doError($command, "Parameters count should be >= 1");
|
55 |
+
}
|
56 |
+
|
57 |
+
$file = strtolower($params[0]);
|
58 |
+
$file = realpath($file);
|
59 |
+
|
60 |
+
if(!file_exists($file)) {
|
61 |
+
return $this->doError($command, "File {$params[0]} doesn't exist");
|
62 |
+
}
|
63 |
+
|
64 |
+
try {
|
65 |
+
$packager = new Mage_Connect_Package($file);
|
66 |
+
$res = $packager->validate();
|
67 |
+
if(!$res) {
|
68 |
+
$this->doError($command, implode("\n", $packager->getErrors()));
|
69 |
+
return;
|
70 |
+
}
|
71 |
+
$packager->save(dirname($file));
|
72 |
+
$this->ui()->output('Done building package');
|
73 |
+
} catch (Exception $e) {
|
74 |
+
$this->doError( $command, $e->getMessage() );
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Display/get dependencies
|
81 |
+
* @param string $command
|
82 |
+
* @param array $options
|
83 |
+
* @param array $params
|
84 |
+
* @return void/array
|
85 |
+
*/
|
86 |
+
public function doPackageDependencies($command, $options, $params)
|
87 |
+
{
|
88 |
+
$this->cleanupParams($params);
|
89 |
+
try {
|
90 |
+
if(count($params) < 2) {
|
91 |
+
return $this->doError($command, "Argument count should be >= 2");
|
92 |
+
}
|
93 |
+
|
94 |
+
$channel = $params[0];
|
95 |
+
$package = $params[1];
|
96 |
+
|
97 |
+
$argVersionMin = isset($params[3]) ? $params[3] : false;
|
98 |
+
$argVersionMax = isset($params[2]) ? $params[2] : false;
|
99 |
+
|
100 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
101 |
+
$packager = $this->getPackager();
|
102 |
+
if($ftp) {
|
103 |
+
list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
|
104 |
+
} else {
|
105 |
+
$cache = $this->getSconfig();
|
106 |
+
$config = $this->config();
|
107 |
+
}
|
108 |
+
$data = $packager->getDependenciesList($channel, $package, $cache, $config, $argVersionMax, $argVersionMin);
|
109 |
+
$this->ui()->output(array($command=> array('data'=>$data['deps'], 'title'=>"Package deps for {$params[1]}: ")));
|
110 |
+
|
111 |
+
} catch (Exception $e) {
|
112 |
+
$this->doError($command, $e->getMessage());
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
public function doConvert($command, $options, $params)
|
117 |
+
{
|
118 |
+
$this->cleanupParams($params);
|
119 |
+
try {
|
120 |
+
if(count($params) < 1) {
|
121 |
+
throw new Exception("Arguments should be: source.tgz [target.tgz]");
|
122 |
+
}
|
123 |
+
$sourceFile = $params[0];
|
124 |
+
$converter = new Mage_Connect_Converter();
|
125 |
+
$targetFile = isset($params[1]) ? $params[1] : false;
|
126 |
+
$result = $converter->convertPearToMage($sourceFile, $targetFile);
|
127 |
+
$this->ui()->output("Saved to: ".$result);
|
128 |
+
} catch (Exception $e) {
|
129 |
+
$this->doError($command, $e->getMessage());
|
130 |
+
}
|
131 |
+
|
132 |
+
}
|
133 |
+
|
134 |
+
}
|
lib/Mage/Connect/Command/Package_Header.php
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
$commands = array(
|
28 |
+
'package' => array(
|
29 |
+
'summary' => 'Build Package',
|
30 |
+
'function' => 'doPackage',
|
31 |
+
'shortcut' => 'p',
|
32 |
+
'options' => array(
|
33 |
+
'nocompress' => array(
|
34 |
+
'shortopt' => 'Z',
|
35 |
+
'doc' => 'Do not gzip the package file'
|
36 |
+
),
|
37 |
+
'showname' => array(
|
38 |
+
'shortopt' => 'n',
|
39 |
+
'doc' => 'Print the name of the packaged file.',
|
40 |
+
),
|
41 |
+
),
|
42 |
+
'doc' => '[descfile] [descfile2]
|
43 |
+
Creates a PEAR package from its description file (usually called
|
44 |
+
package.xml). If a second packagefile is passed in, then
|
45 |
+
the packager will check to make sure that one is a package.xml
|
46 |
+
version 1.0, and the other is a package.xml version 2.0. The
|
47 |
+
package.xml version 1.0 will be saved as "package.xml" in the archive,
|
48 |
+
and the other as "package2.xml" in the archive"
|
49 |
+
'
|
50 |
+
),
|
51 |
+
'package-dependencies' => array(
|
52 |
+
'summary' => 'Show package dependencies',
|
53 |
+
'function' => 'doPackageDependencies',
|
54 |
+
'shortcut' => 'pd',
|
55 |
+
'options' => array(),
|
56 |
+
'doc' => '<package-file> or <package.xml> or <install-package-name>
|
57 |
+
List all dependencies the package has.
|
58 |
+
Can take a tgz / tar file, package.xml or a package name of an installed package.'
|
59 |
+
),
|
60 |
+
'convert' => array(
|
61 |
+
'summary' => 'Convert old magento PEAR package to new format',
|
62 |
+
'function' => 'doConvert',
|
63 |
+
'shortcut' => 'conv',
|
64 |
+
'options' => array(),
|
65 |
+
'doc' => ''
|
66 |
+
),
|
67 |
+
);
|
lib/Mage/Connect/Command/Registry.php
ADDED
@@ -0,0 +1,175 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
final class Mage_Connect_Command_Registry
|
28 |
+
extends Mage_Connect_Command
|
29 |
+
{
|
30 |
+
|
31 |
+
/**
|
32 |
+
* List-installed callback
|
33 |
+
* @param string $command
|
34 |
+
* @param array $options
|
35 |
+
* @param array $params
|
36 |
+
* @return void
|
37 |
+
*/
|
38 |
+
public function doList($command, $options, $params)
|
39 |
+
{
|
40 |
+
$this->cleanupParams($params);
|
41 |
+
try {
|
42 |
+
$packager = $this->getPackager();
|
43 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
44 |
+
if($ftp) {
|
45 |
+
list($cache, $ftpObj) = $packager->getRemoteCache($ftp);
|
46 |
+
} else {
|
47 |
+
$cache = $this->getSconfig();
|
48 |
+
}
|
49 |
+
if(!empty($params[0])) {
|
50 |
+
$chanName = $conf->chanName($params[0]);
|
51 |
+
$data = $cache->getInstalledPackages($chanName);
|
52 |
+
} else {
|
53 |
+
$data = $cache->getInstalledPackages();
|
54 |
+
}
|
55 |
+
if($ftp) {
|
56 |
+
@unlink($cache->getFilename());
|
57 |
+
}
|
58 |
+
$this->ui()->output(array($command=>array('data'=>$data, 'channel-title'=>"Installed package for channel '%s' :")));
|
59 |
+
} catch (Exception $e) {
|
60 |
+
if($ftp) {
|
61 |
+
@unlink($cache->getFilename());
|
62 |
+
}
|
63 |
+
$this->doError($command, $e->getMessage());
|
64 |
+
}
|
65 |
+
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* list-files callback
|
70 |
+
* @param string $command
|
71 |
+
* @param array $options
|
72 |
+
* @param array $params
|
73 |
+
* @return void
|
74 |
+
*/
|
75 |
+
public function doFileList($command, $options, $params)
|
76 |
+
{
|
77 |
+
$this->cleanupParams($params);
|
78 |
+
//$this->splitPackageArgs($params);
|
79 |
+
try {
|
80 |
+
$channel = false;
|
81 |
+
if(count($params) < 2) {
|
82 |
+
throw new Exception("Argument count should be = 2");
|
83 |
+
}
|
84 |
+
$channel = $params[0];
|
85 |
+
$package = $params[1];
|
86 |
+
|
87 |
+
$packager = $this->getPackager();
|
88 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
89 |
+
if($ftp) {
|
90 |
+
list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
|
91 |
+
} else {
|
92 |
+
$cache = $this->getSconfig();
|
93 |
+
$confif = $this->config();
|
94 |
+
}
|
95 |
+
if(!$cache->hasPackage($channel, $package)) {
|
96 |
+
return $this->ui()->output("No package found: {$channel}/{$package}");
|
97 |
+
}
|
98 |
+
|
99 |
+
$p = $cache->getPackageObject($channel, $package);
|
100 |
+
$contents = $p->getContents();
|
101 |
+
if($ftp) {
|
102 |
+
$ftpObj->close();
|
103 |
+
}
|
104 |
+
if(!count($contents)) {
|
105 |
+
return $this->ui()->output("No contents for package {$package}");
|
106 |
+
}
|
107 |
+
$title = ("Contents of '{$package}': ");
|
108 |
+
if($ftp) {
|
109 |
+
@unlink($config->getFilename());
|
110 |
+
@unlink($cache->getFilename());
|
111 |
+
}
|
112 |
+
|
113 |
+
$this->ui()->output(array($command=>array('data'=>$contents, 'title'=>$title)));
|
114 |
+
|
115 |
+
} catch (Exception $e) {
|
116 |
+
if($ftp) {
|
117 |
+
@unlink($config->getFilename());
|
118 |
+
@unlink($cache->getFilename());
|
119 |
+
}
|
120 |
+
$this->doError($command, $e->getMessage());
|
121 |
+
}
|
122 |
+
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Installed package info
|
127 |
+
* info command callback
|
128 |
+
* @param string $command
|
129 |
+
* @param array $options
|
130 |
+
* @param array $params
|
131 |
+
* @return
|
132 |
+
*/
|
133 |
+
public function doInfo($command, $options, $params)
|
134 |
+
{
|
135 |
+
$this->cleanupParams($params);
|
136 |
+
//$this->splitPackageArgs($params);
|
137 |
+
|
138 |
+
try {
|
139 |
+
$channel = false;
|
140 |
+
if(count($params) < 2) {
|
141 |
+
throw new Exception("Argument count should be = 2");
|
142 |
+
}
|
143 |
+
$channel = $params[0];
|
144 |
+
$package = $params[1];
|
145 |
+
$packager = $this->getPackager();
|
146 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
147 |
+
if($ftp) {
|
148 |
+
list($cache, $ftpObj) = $packager->getRemoteCache($ftp);
|
149 |
+
} else {
|
150 |
+
$cache = $this->getSconfig();
|
151 |
+
}
|
152 |
+
|
153 |
+
if(!$cache->isChannel($channel)) {
|
154 |
+
throw new Exception("'{$channel}' is not a valid installed channel name/uri");
|
155 |
+
}
|
156 |
+
$channelUri = $cache->chanUrl($channel);
|
157 |
+
$rest = $this->rest();
|
158 |
+
$rest->setChannel($channelUri);
|
159 |
+
$releases = $rest->getReleases($package);
|
160 |
+
if(false === $releases) {
|
161 |
+
throw new Exception("No information found about {$channel}/{$package}");
|
162 |
+
}
|
163 |
+
$data = array($command => array('releases'=>$releases));
|
164 |
+
if($ftp) {
|
165 |
+
@unlink($cache->getFilename());
|
166 |
+
}
|
167 |
+
$this->ui()->output($data);
|
168 |
+
} catch (Exception $e) {
|
169 |
+
if($ftp) {
|
170 |
+
@unlink($cache->getFilename());
|
171 |
+
}
|
172 |
+
$this->doError($command, $e->getMessage());
|
173 |
+
}
|
174 |
+
}
|
175 |
+
}
|
lib/Mage/Connect/Command/Registry_Header.php
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
$commands = array(
|
28 |
+
'list-installed' => array(
|
29 |
+
'summary' => 'List Installed Packages In The Default Channel',
|
30 |
+
'function' => 'doList',
|
31 |
+
'shortcut' => 'l',
|
32 |
+
'options' => array(
|
33 |
+
'channel' => array(
|
34 |
+
'shortopt' => 'c',
|
35 |
+
'doc' => 'list installed packages from this channel',
|
36 |
+
'arg' => 'CHAN',
|
37 |
+
),
|
38 |
+
'allchannels' => array(
|
39 |
+
'shortopt' => 'a',
|
40 |
+
'doc' => 'list installed packages from all channels',
|
41 |
+
),
|
42 |
+
),
|
43 |
+
'doc' => '<package>
|
44 |
+
If invoked without parameters, this command lists the PEAR packages
|
45 |
+
installed in your php_dir ({config php_dir}). With a parameter, it
|
46 |
+
lists the files in a package.
|
47 |
+
',
|
48 |
+
),
|
49 |
+
'list-files' => array(
|
50 |
+
'summary' => 'List Files In Installed Package',
|
51 |
+
'function' => 'doFileList',
|
52 |
+
'shortcut' => 'fl',
|
53 |
+
'options' => array(),
|
54 |
+
'doc' => '<package>
|
55 |
+
List the files in an installed package.
|
56 |
+
'
|
57 |
+
),
|
58 |
+
'info' => array(
|
59 |
+
'summary' => 'Display information about a package',
|
60 |
+
'function' => 'doInfo',
|
61 |
+
'shortcut' => 'in',
|
62 |
+
'options' => array(),
|
63 |
+
'doc' => '<package>
|
64 |
+
Displays information about a package. The package argument may be a
|
65 |
+
local package file, an URL to a package file, or the name of an
|
66 |
+
installed package.'
|
67 |
+
)
|
68 |
+
);
|
lib/Mage/Connect/Command/Remote.php
ADDED
@@ -0,0 +1,226 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
final class Mage_Connect_Command_Remote
|
28 |
+
extends Mage_Connect_Command
|
29 |
+
{
|
30 |
+
|
31 |
+
/**
|
32 |
+
* List-upgrades callback
|
33 |
+
* @param srting $command
|
34 |
+
* @param array $options
|
35 |
+
* @param array $params
|
36 |
+
* @return void
|
37 |
+
*/
|
38 |
+
public function doListUpgrades($command, $options, $params)
|
39 |
+
{
|
40 |
+
|
41 |
+
$this->cleanupParams($params);
|
42 |
+
try {
|
43 |
+
$packager = new Mage_Connect_Packager();
|
44 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
45 |
+
if($ftp) {
|
46 |
+
list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
|
47 |
+
} else {
|
48 |
+
$cache = $this->getSconfig();
|
49 |
+
$config = $this->config();
|
50 |
+
}
|
51 |
+
|
52 |
+
if(!empty($params[0])) {
|
53 |
+
$channels = $params[0];
|
54 |
+
$cache->getChannel($channels);
|
55 |
+
} else {
|
56 |
+
$channels = $cache->getChannelNames();
|
57 |
+
}
|
58 |
+
$ups = $packager->getUpgradesList($channels, $cache, $config);
|
59 |
+
|
60 |
+
if(count($ups)) {
|
61 |
+
$data = array($command => array('data'=>$ups));
|
62 |
+
} else {
|
63 |
+
$data = "No upgrades available";
|
64 |
+
}
|
65 |
+
$this->ui()->output($data);
|
66 |
+
} catch(Exception $e) {
|
67 |
+
$this->doError($command, $e->getMessage());
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
|
72 |
+
/**
|
73 |
+
* List available
|
74 |
+
* @param $command
|
75 |
+
* @param $options
|
76 |
+
* @param $params
|
77 |
+
* @return unknown_type
|
78 |
+
*/
|
79 |
+
|
80 |
+
public function doListAvailable($command, $options, $params)
|
81 |
+
{
|
82 |
+
$this->cleanupParams($params);
|
83 |
+
|
84 |
+
try {
|
85 |
+
$packager = new Mage_Connect_Packager();
|
86 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
87 |
+
if($ftp) {
|
88 |
+
list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
|
89 |
+
} else {
|
90 |
+
$cache = $this->getSconfig();
|
91 |
+
$config = $this->config();
|
92 |
+
}
|
93 |
+
|
94 |
+
if(!empty($params[0])) {
|
95 |
+
$channels = array($params[0]);
|
96 |
+
$cache->getChannel($channels[0]);
|
97 |
+
} else {
|
98 |
+
$channels = $cache->getChannelNames();
|
99 |
+
}
|
100 |
+
|
101 |
+
|
102 |
+
|
103 |
+
$packs = array();
|
104 |
+
foreach ($channels as $channel) {
|
105 |
+
try {
|
106 |
+
$chan = $cache->getChannel($channel);
|
107 |
+
$uri = $cache->chanUrl($channel);
|
108 |
+
|
109 |
+
$rest = $this->rest();
|
110 |
+
$rest->setChannel($uri);
|
111 |
+
|
112 |
+
$packages = $rest->getPackages();
|
113 |
+
if(!count($packages)) {
|
114 |
+
$this->ui()->output("Channel '{$channel}' has no packages");
|
115 |
+
continue;
|
116 |
+
}
|
117 |
+
$packs[$channel]['title'] = "Packages for channel '".$channel."':";
|
118 |
+
foreach($packages as $p) {
|
119 |
+
$packageName = $p['n'];
|
120 |
+
$releases = array();
|
121 |
+
foreach($p['r'] as $k=>$r) {
|
122 |
+
$releases[$r] = $rest->shortStateToLong($k);
|
123 |
+
}
|
124 |
+
$packs[$channel]['packages'][$packageName]['releases'] = $releases;
|
125 |
+
}
|
126 |
+
} catch (Exception $e) {
|
127 |
+
$this->doError($command, $e->getMessage());
|
128 |
+
}
|
129 |
+
}
|
130 |
+
$dataOut = array();
|
131 |
+
$dataOut[$command]= array('data'=>$packs);
|
132 |
+
$this->ui()->output($dataOut);
|
133 |
+
|
134 |
+
} catch(Exception $e) {
|
135 |
+
$this->doError($command, $e->getMessage());
|
136 |
+
}
|
137 |
+
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Download command callback
|
142 |
+
*
|
143 |
+
* @param string $command
|
144 |
+
* @param array $options
|
145 |
+
* @param array $params
|
146 |
+
* @return void
|
147 |
+
*/
|
148 |
+
public function doDownload($command, $options, $params)
|
149 |
+
{
|
150 |
+
$this->cleanupParams($params);
|
151 |
+
//$this->splitPackageArgs($params);
|
152 |
+
try {
|
153 |
+
if(count($params) < 2) {
|
154 |
+
throw new Exception("Arguments should be: channel Package");
|
155 |
+
}
|
156 |
+
|
157 |
+
$channel = $params[0];
|
158 |
+
$package = $params[1];
|
159 |
+
|
160 |
+
$packager = $this->getPackager();
|
161 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
162 |
+
if($ftp) {
|
163 |
+
list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
|
164 |
+
} else {
|
165 |
+
$cache = $this->getSconfig();
|
166 |
+
$config = $this->config();
|
167 |
+
}
|
168 |
+
|
169 |
+
$chan = $cache->getChannel($channel);
|
170 |
+
$uri = $cache->chanUrl($channel);
|
171 |
+
|
172 |
+
$rest = $this->rest();
|
173 |
+
$rest->setChannel($uri);
|
174 |
+
$c = $rest->getReleases($package);
|
175 |
+
if(!count($c)) {
|
176 |
+
throw new Exception("No releases found for package");
|
177 |
+
}
|
178 |
+
$version = $cache->detectVersionFromRestArray($c);
|
179 |
+
$dir = $config->getChannelCacheDir($channel);
|
180 |
+
$file = $dir.DIRECTORY_SEPARATOR.$package."-".$version.".tgz";
|
181 |
+
$rest->downloadPackageFileOfRelease($package, $version, $file);
|
182 |
+
if($ftp) {
|
183 |
+
@unlink($config->getFilename());
|
184 |
+
@unlink($cache->getFilename());
|
185 |
+
}
|
186 |
+
$this->ui()->output("Saved to: ". $file);
|
187 |
+
} catch (Exception $e) {
|
188 |
+
if($ftp) {
|
189 |
+
@unlink($config->getFilename());
|
190 |
+
@unlink($cache->getFilename());
|
191 |
+
}
|
192 |
+
$this->doError($command, $e->getMessage());
|
193 |
+
}
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Clear cache command callback
|
198 |
+
* @param string $command
|
199 |
+
* @param array $options
|
200 |
+
* @param array $params
|
201 |
+
* @return void
|
202 |
+
*/
|
203 |
+
public function doClearCache($command, $options, $params)
|
204 |
+
{
|
205 |
+
$this->cleanupParams($params);
|
206 |
+
try {
|
207 |
+
$packager = new Mage_Connect_Packager();
|
208 |
+
$ftp = empty($options['ftp']) ? false : $options['ftp'];
|
209 |
+
if($ftp) {
|
210 |
+
list($cache, $ftpObj) = $packager->getRemoteCache($ftp);
|
211 |
+
$cache->clear();
|
212 |
+
$packager->writeToRemoteCache($cache, $ftpObj);
|
213 |
+
} else {
|
214 |
+
$cache = $this->getSconfig();
|
215 |
+
$cache->clear();
|
216 |
+
}
|
217 |
+
} catch (Exception $e) {
|
218 |
+
$this->doError($command, $e->getMessage());
|
219 |
+
}
|
220 |
+
}
|
221 |
+
|
222 |
+
|
223 |
+
|
224 |
+
|
225 |
+
|
226 |
+
}
|
lib/Mage/Connect/Command/Remote_Header.php
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
$commands = array(
|
28 |
+
'list-upgrades' => array(
|
29 |
+
'summary' => 'List Available Upgrades',
|
30 |
+
'function' => 'doListUpgrades',
|
31 |
+
'shortcut' => 'lu',
|
32 |
+
'options' => array(
|
33 |
+
'channelinfo' => array(
|
34 |
+
'shortopt' => 'i',
|
35 |
+
'doc' => 'output fully channel-aware data, even on failure',
|
36 |
+
),
|
37 |
+
),
|
38 |
+
'doc' => '[preferred_state]
|
39 |
+
List releases on the server of packages you have installed where
|
40 |
+
a newer version is available with the same release state (stable etc.)
|
41 |
+
or the state passed as the second parameter.'
|
42 |
+
),
|
43 |
+
'list-available' => array(
|
44 |
+
'summary' => 'List Available Packages',
|
45 |
+
'function' => 'doListAvailable',
|
46 |
+
'shortcut' => 'la',
|
47 |
+
'options' => array(
|
48 |
+
'channel' =>
|
49 |
+
array(
|
50 |
+
'shortopt' => 'c',
|
51 |
+
'doc' => 'specify a channel other than the default channel',
|
52 |
+
'arg' => 'CHAN',
|
53 |
+
),
|
54 |
+
'channelinfo' => array(
|
55 |
+
'shortopt' => 'i',
|
56 |
+
'doc' => 'output fully channel-aware data, even on failure',
|
57 |
+
),
|
58 |
+
),
|
59 |
+
'doc' => '
|
60 |
+
Lists the packages available on the configured server along with the
|
61 |
+
latest stable release of each package.',
|
62 |
+
),
|
63 |
+
'download' => array(
|
64 |
+
'summary' => 'Download Package',
|
65 |
+
'function' => 'doDownload',
|
66 |
+
'shortcut' => 'd',
|
67 |
+
'options' => array(
|
68 |
+
'nocompress' => array(
|
69 |
+
'shortopt' => 'Z',
|
70 |
+
'doc' => 'download an uncompressed (.tar) file',
|
71 |
+
),
|
72 |
+
),
|
73 |
+
'doc' => '<package>...
|
74 |
+
Download package tarballs. The files will be named as suggested by the
|
75 |
+
server, for example if you download the DB package and the latest stable
|
76 |
+
version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.',
|
77 |
+
),
|
78 |
+
'clear-cache' => array(
|
79 |
+
'summary' => 'Clear Web Services Cache',
|
80 |
+
'function' => 'doClearCache',
|
81 |
+
'shortcut' => 'cc',
|
82 |
+
'options' => array(),
|
83 |
+
'doc' => '
|
84 |
+
Clear the XML-RPC/REST cache. See also the cache_ttl configuration
|
85 |
+
parameter.
|
86 |
+
',
|
87 |
+
),
|
88 |
+
);
|
lib/Mage/Connect/Config.php
ADDED
@@ -0,0 +1,265 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Mage_Connect_Config
|
4 |
+
implements Iterator
|
5 |
+
{
|
6 |
+
protected $_configFile;
|
7 |
+
const HEADER = "::ConnectConfig::v::1.0::";
|
8 |
+
const DEFAULT_DOWNLOADER_PATH = "downloader";
|
9 |
+
const DEFAULT_CACHE_PATH = ".cache";
|
10 |
+
|
11 |
+
protected $properties = array();
|
12 |
+
|
13 |
+
protected function initProperties()
|
14 |
+
{
|
15 |
+
$this->properties = array (
|
16 |
+
'php_ini' => array(
|
17 |
+
'type' => 'file',
|
18 |
+
'value' => '',
|
19 |
+
'prompt' => 'location of php.ini',
|
20 |
+
'doc' => "It's a location of PHP.ini to use blah",
|
21 |
+
'possible' => '/path/php.ini',
|
22 |
+
),
|
23 |
+
'protocol' => array(
|
24 |
+
'type' => 'set',
|
25 |
+
'value' => 'http',
|
26 |
+
'prompt' => 'preffered protocol',
|
27 |
+
'doc' => 'preffered protocol',
|
28 |
+
'rules' => array('http', 'ftp')
|
29 |
+
),
|
30 |
+
'preferred_state' => array(
|
31 |
+
'type' => 'set',
|
32 |
+
'value' => 'stable',
|
33 |
+
'prompt' => 'preferred package state',
|
34 |
+
'doc' => 'preferred package state',
|
35 |
+
'rules' => array('beta','alpha','stable','devel')
|
36 |
+
),
|
37 |
+
'global_dir_mode' => array (
|
38 |
+
'type' => 'octal',
|
39 |
+
'value' => 0777,
|
40 |
+
'prompt' => 'directory creation mode',
|
41 |
+
'doc' => 'directory creation mode',
|
42 |
+
'possible' => '0777, 0666 etc.',
|
43 |
+
),
|
44 |
+
'global_file_mode' => array (
|
45 |
+
'type' => 'octal',
|
46 |
+
'value' => 0666,
|
47 |
+
'prompt' => 'file creation mode',
|
48 |
+
'doc' => 'file creation mode',
|
49 |
+
'possible' => '0777, 0666 etc.',
|
50 |
+
),
|
51 |
+
'downloader_path' => array(
|
52 |
+
'type' => 'dir',
|
53 |
+
'value' => 'downloader',
|
54 |
+
'prompt' => 'relative path, location of magento downloader',
|
55 |
+
'doc' => "relative path, location of magento downloader",
|
56 |
+
'possible' => 'path',
|
57 |
+
),
|
58 |
+
'magento_root' => array(
|
59 |
+
'type' => 'dir',
|
60 |
+
'value' => '',
|
61 |
+
'prompt' => 'location of magento root dir',
|
62 |
+
'doc' => "Location of magento",
|
63 |
+
'possible' => '/path',
|
64 |
+
),
|
65 |
+
'root_channel' => array(
|
66 |
+
'type' => 'string',
|
67 |
+
'value' => 'core',
|
68 |
+
'prompt' => '',
|
69 |
+
'doc' => "",
|
70 |
+
'possible' => '',
|
71 |
+
),
|
72 |
+
|
73 |
+
);
|
74 |
+
|
75 |
+
}
|
76 |
+
|
77 |
+
public function getDownloaderPath()
|
78 |
+
{
|
79 |
+
return $this->magento_root . DIRECTORY_SEPARATOR . $this->downloader_path;
|
80 |
+
}
|
81 |
+
|
82 |
+
public function getPackagesCacheDir()
|
83 |
+
{
|
84 |
+
return $this->getDownloaderPath() . DIRECTORY_SEPARATOR . self::DEFAULT_CACHE_PATH;
|
85 |
+
}
|
86 |
+
|
87 |
+
public function getChannelCacheDir($channel)
|
88 |
+
{
|
89 |
+
$channel = trim( $channel, "\\/");
|
90 |
+
return $this->getPackagesCacheDir(). DIRECTORY_SEPARATOR . $channel;
|
91 |
+
}
|
92 |
+
|
93 |
+
|
94 |
+
public function __construct($configFile = "connect.cfg")
|
95 |
+
{
|
96 |
+
$this->initProperties();
|
97 |
+
$this->_configFile = $configFile;
|
98 |
+
$this->load();
|
99 |
+
}
|
100 |
+
|
101 |
+
public function getFilename()
|
102 |
+
{
|
103 |
+
return $this->_configFile;
|
104 |
+
}
|
105 |
+
|
106 |
+
public function load()
|
107 |
+
{
|
108 |
+
/**
|
109 |
+
* Trick: open in append mode to read,
|
110 |
+
* place pointer to begin
|
111 |
+
* create if not exists
|
112 |
+
*/
|
113 |
+
$f = fopen($this->_configFile, "a+");
|
114 |
+
fseek($f, 0, SEEK_SET);
|
115 |
+
$size = filesize($this->_configFile);
|
116 |
+
if(!$size) {
|
117 |
+
$this->store();
|
118 |
+
return;
|
119 |
+
}
|
120 |
+
|
121 |
+
$headerLen = strlen(self::HEADER);
|
122 |
+
$contents = fread($f, $headerLen);
|
123 |
+
|
124 |
+
if(self::HEADER != $contents) {
|
125 |
+
$this->store();
|
126 |
+
return;
|
127 |
+
}
|
128 |
+
|
129 |
+
$size -= $headerLen;
|
130 |
+
$contents = fread($f, $size);
|
131 |
+
|
132 |
+
$data = @unserialize($contents);
|
133 |
+
if($data === unserialize(false)) {
|
134 |
+
$this->store();
|
135 |
+
return;
|
136 |
+
}
|
137 |
+
foreach($data as $k=>$v) {
|
138 |
+
$this->$k = $v;
|
139 |
+
}
|
140 |
+
fclose($f);
|
141 |
+
}
|
142 |
+
|
143 |
+
public function store()
|
144 |
+
{
|
145 |
+
$data = serialize($this->toArray());
|
146 |
+
$f = @fopen($this->_configFile, "w+");
|
147 |
+
@fwrite($f, self::HEADER);
|
148 |
+
@fwrite($f, $data);
|
149 |
+
@fclose($f);
|
150 |
+
}
|
151 |
+
|
152 |
+
|
153 |
+
public function validate($key, $val)
|
154 |
+
{
|
155 |
+
$rules = $this->extractField($key, 'rules');
|
156 |
+
if(null === $rules) {
|
157 |
+
return true;
|
158 |
+
} elseif( is_array($rules) ) {
|
159 |
+
return in_array($val, $rules);
|
160 |
+
}
|
161 |
+
return false;
|
162 |
+
}
|
163 |
+
|
164 |
+
public function possible($key)
|
165 |
+
{
|
166 |
+
$data = $this->getKey($key);
|
167 |
+
if(! $data) {
|
168 |
+
return null;
|
169 |
+
}
|
170 |
+
if('set' == $data['type']) {
|
171 |
+
return implode("|", $data['rules']);
|
172 |
+
}
|
173 |
+
if(!empty($data['possible'])) {
|
174 |
+
return $data['possible'];
|
175 |
+
}
|
176 |
+
return "<".$data['type'].">";
|
177 |
+
}
|
178 |
+
|
179 |
+
public function type($key)
|
180 |
+
{
|
181 |
+
return $this->extractField($key, 'type');
|
182 |
+
}
|
183 |
+
|
184 |
+
public function doc($key)
|
185 |
+
{
|
186 |
+
return $this->extractField($key, 'doc');
|
187 |
+
}
|
188 |
+
|
189 |
+
|
190 |
+
public function extractField($key, $field)
|
191 |
+
{
|
192 |
+
if(!isset($this->properties[$key][$field])) {
|
193 |
+
return null;
|
194 |
+
}
|
195 |
+
return $this->properties[$key][$field];
|
196 |
+
}
|
197 |
+
|
198 |
+
|
199 |
+
public function hasKey($fld)
|
200 |
+
{
|
201 |
+
return isset($this->properties[$fld]);
|
202 |
+
}
|
203 |
+
|
204 |
+
public function getKey($fld)
|
205 |
+
{
|
206 |
+
if($this->hasKey($fld)) {
|
207 |
+
return $this->properties[$fld];
|
208 |
+
}
|
209 |
+
return null;
|
210 |
+
}
|
211 |
+
|
212 |
+
public function rewind() {
|
213 |
+
reset($this->properties);
|
214 |
+
}
|
215 |
+
|
216 |
+
public function valid() {
|
217 |
+
return current($this->properties) !== false;
|
218 |
+
}
|
219 |
+
|
220 |
+
public function key() {
|
221 |
+
return key($this->properties);
|
222 |
+
}
|
223 |
+
|
224 |
+
public function current() {
|
225 |
+
return current($this->properties);
|
226 |
+
}
|
227 |
+
|
228 |
+
public function next() {
|
229 |
+
next($this->properties);
|
230 |
+
}
|
231 |
+
|
232 |
+
public function __get($var)
|
233 |
+
{
|
234 |
+
if (isset($this->properties[$var]['value'])) {
|
235 |
+
return $this->properties[$var]['value'];
|
236 |
+
}
|
237 |
+
return null;
|
238 |
+
}
|
239 |
+
|
240 |
+
public function __set($var, $value)
|
241 |
+
{
|
242 |
+
if (is_string($value)) {
|
243 |
+
$value = trim($value);
|
244 |
+
}
|
245 |
+
if (isset($this->properties[$var])) {
|
246 |
+
if ($value === null) {
|
247 |
+
$value = '';
|
248 |
+
}
|
249 |
+
if($this->properties[$var]['value'] !== $value) {
|
250 |
+
$this->properties[$var]['value'] = $value;
|
251 |
+
$this->store();
|
252 |
+
}
|
253 |
+
}
|
254 |
+
}
|
255 |
+
|
256 |
+
public function toArray($withRules = false)
|
257 |
+
{
|
258 |
+
$out = array();
|
259 |
+
foreach($this as $k=>$v) {
|
260 |
+
$out[$k] = $withRules ? $v : $v['value'];
|
261 |
+
}
|
262 |
+
return $out;
|
263 |
+
}
|
264 |
+
|
265 |
+
}
|
lib/Mage/Connect/Converter.php
ADDED
@@ -0,0 +1,337 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Magento
|
5 |
+
*
|
6 |
+
* NOTICE OF LICENSE
|
7 |
+
*
|
8 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
9 |
+
* that is bundled with this package in the file LICENSE.txt.
|
10 |
+
* It is also available through the world-wide-web at this URL:
|
11 |
+
* http://opensource.org/licenses/osl-3.0.php
|
12 |
+
* If you did not receive a copy of the license and are unable to
|
13 |
+
* obtain it through the world-wide-web, please send an email
|
14 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
15 |
+
*
|
16 |
+
* DISCLAIMER
|
17 |
+
*
|
18 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
19 |
+
* versions in the future. If you wish to customize Magento for your
|
20 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
21 |
+
*
|
22 |
+
* @category Mage
|
23 |
+
* @package Mage_Connect
|
24 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
25 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
26 |
+
*/
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Class for convertiong old magento PEAR packages to new one
|
30 |
+
*
|
31 |
+
* @category Mage
|
32 |
+
* @package Mage_Connect
|
33 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
34 |
+
*/
|
35 |
+
|
36 |
+
final class Mage_Connect_Converter
|
37 |
+
{
|
38 |
+
protected $_archiver;
|
39 |
+
|
40 |
+
/**
|
41 |
+
*
|
42 |
+
* @return Mage_Archive
|
43 |
+
*/
|
44 |
+
public function arc()
|
45 |
+
{
|
46 |
+
if(!$this->_archiver) {
|
47 |
+
$this->_archiver = new Mage_Archive();
|
48 |
+
}
|
49 |
+
return $this->_archiver;
|
50 |
+
}
|
51 |
+
|
52 |
+
public function newPackage()
|
53 |
+
{
|
54 |
+
return new Mage_Connect_Package();
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
*
|
59 |
+
* @return Pear_Package_Parser_v2
|
60 |
+
*/
|
61 |
+
public function oldPackageReader()
|
62 |
+
{
|
63 |
+
return new Pear_Package_Parser_v2();
|
64 |
+
}
|
65 |
+
|
66 |
+
|
67 |
+
public function __construct()
|
68 |
+
{
|
69 |
+
|
70 |
+
}
|
71 |
+
|
72 |
+
|
73 |
+
public function convertChannelName($channel)
|
74 |
+
{
|
75 |
+
return str_replace("connect.magentocommerce.com/", "", $channel);
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Convert package dependencies - urls - by ref
|
80 |
+
* @param array $deps ref to array
|
81 |
+
* @return void
|
82 |
+
*/
|
83 |
+
public function convertPackageDependencies($oldDeps)
|
84 |
+
{
|
85 |
+
$out = array();
|
86 |
+
if(empty($oldDeps['required']['package'])) {
|
87 |
+
return $out;
|
88 |
+
}
|
89 |
+
$deps = $oldDeps['required']['package'];
|
90 |
+
if(!isset($deps[0])) {
|
91 |
+
$deps = array($deps);
|
92 |
+
}
|
93 |
+
for($i=0, $c=count($deps); $i<$c; $i++) {
|
94 |
+
$deps[$i]['min_version'] = isset($deps[$i]['min']) ? $deps[$i]['min'] : false;
|
95 |
+
$deps[$i]['max_version'] = isset($deps[$i]['max']) ? $deps[$i]['max'] : false;
|
96 |
+
$deps[$i]['channel'] = $this->convertChannelName($deps[$i]['channel']);
|
97 |
+
$out[] = $deps[$i];
|
98 |
+
}
|
99 |
+
|
100 |
+
return $out;
|
101 |
+
}
|
102 |
+
|
103 |
+
public function convertLicense($oldLicense)
|
104 |
+
{
|
105 |
+
if(is_scalar($oldLicense)) {
|
106 |
+
return $oldLicense;
|
107 |
+
}
|
108 |
+
return array($oldLicense['_content'], $oldLicense['attribs']['uri']);
|
109 |
+
}
|
110 |
+
|
111 |
+
public function convertMaintainers($maintainers)
|
112 |
+
{
|
113 |
+
if(!is_array($maintainers) || !count($maintainers)) {
|
114 |
+
return array();
|
115 |
+
}
|
116 |
+
$out = array();
|
117 |
+
foreach($maintainers as $row) {
|
118 |
+
$out[] = array('name'=>$row['name'], 'email'=>$row['email'], 'user'=>'auto-converted');
|
119 |
+
}
|
120 |
+
return $out;
|
121 |
+
}
|
122 |
+
|
123 |
+
protected $fileMap = array();
|
124 |
+
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Conver pear package object to magento object
|
128 |
+
* @param Pear_Package_V2 $pearObject
|
129 |
+
* @return Mage_Connect_Package
|
130 |
+
*/
|
131 |
+
|
132 |
+
public function convertPackageObject($pearObject)
|
133 |
+
{
|
134 |
+
$data = array();
|
135 |
+
$mageObject = $this->newPackage();
|
136 |
+
|
137 |
+
|
138 |
+
|
139 |
+
$map = array (
|
140 |
+
'name' => null,
|
141 |
+
'version' => array('getterArgs' => array('release')
|
142 |
+
),
|
143 |
+
'package_deps' => array( 'getter'=>'getDependencies',
|
144 |
+
'converter'=>'convertPackageDependencies',
|
145 |
+
'setter'=>'setDependencyPackages',
|
146 |
+
),
|
147 |
+
'stability' => array( 'getter'=>'getState',
|
148 |
+
'getterArgs' => array('release'),
|
149 |
+
),
|
150 |
+
'license' => array( 'getterArgs' => array(true),
|
151 |
+
'converter' => 'convertLicense',
|
152 |
+
'noArrayWrap' => true,
|
153 |
+
),
|
154 |
+
'summary' => null,
|
155 |
+
'description' => null,
|
156 |
+
'notes' => null,
|
157 |
+
'date' => null,
|
158 |
+
'time' => null,
|
159 |
+
'authors' => array( 'converter' => 'convertMaintainers',
|
160 |
+
'getter' => 'getMaintainers',
|
161 |
+
),
|
162 |
+
'channel' => array( 'converter' => 'convertChannelName',
|
163 |
+
|
164 |
+
),
|
165 |
+
|
166 |
+
);
|
167 |
+
foreach($map as $field=>$rules) {
|
168 |
+
|
169 |
+
if(empty($rules)) {
|
170 |
+
$rules = array('setter'=> '', 'getter'=> '');
|
171 |
+
}
|
172 |
+
|
173 |
+
if(empty($rules['getter'])) {
|
174 |
+
$rules['getter'] = 'get'. ucfirst($field);
|
175 |
+
}
|
176 |
+
|
177 |
+
$useSetter = empty($rules['noSetter']);
|
178 |
+
$useGetter = empty($rules['noGetter']);
|
179 |
+
|
180 |
+
|
181 |
+
if(empty($rules['setter'])) {
|
182 |
+
$rules['setter'] = 'set'. ucfirst($field);
|
183 |
+
}
|
184 |
+
if(empty($rules['getterArgs'])) {
|
185 |
+
$rules['getterArgs'] = array();
|
186 |
+
} elseif(!is_array($rules['getterArgs'])) {
|
187 |
+
throw new Exception("Invalid 'getterArgs' for '{$field}', should be array");
|
188 |
+
}
|
189 |
+
|
190 |
+
if($useGetter && !method_exists($pearObject, $rules['getter'])) {
|
191 |
+
$mName = get_class($pearObject)."::".$rules['getter'];
|
192 |
+
throw new Exception('No getter method exists: '.$mName);
|
193 |
+
}
|
194 |
+
|
195 |
+
if($useSetter && !method_exists($mageObject, $rules['setter'])) {
|
196 |
+
$mName = get_class($mageObject)."::".$rules['setter'];
|
197 |
+
throw new Exception('No setter method exists: '.$mName);
|
198 |
+
}
|
199 |
+
|
200 |
+
$useConverter = !empty($rules['converter']);
|
201 |
+
|
202 |
+
if($useConverter && false === method_exists($this, $rules['converter'])) {
|
203 |
+
$mName = get_class($this)."::".$rules['converter'];
|
204 |
+
throw new Exception('No converter method exists: '.$mName);
|
205 |
+
}
|
206 |
+
|
207 |
+
if($useGetter) {
|
208 |
+
$getData = call_user_func_array(array($pearObject, $rules['getter']), $rules['getterArgs']);
|
209 |
+
} else {
|
210 |
+
$getData = array();
|
211 |
+
}
|
212 |
+
|
213 |
+
if($useConverter) {
|
214 |
+
$args = array();
|
215 |
+
if(!$useGetter && !$useSetter) {
|
216 |
+
$args = array($pearObject, $mageObject);
|
217 |
+
} elseif(!$useSetter) {
|
218 |
+
$args = array($mageObject, $getData);
|
219 |
+
} else {
|
220 |
+
$args = array($getData);
|
221 |
+
}
|
222 |
+
$getData = call_user_func_array(array($this, $rules['converter']), $args);
|
223 |
+
}
|
224 |
+
|
225 |
+
$noWrap = !empty($rules['noArrayWrap']);
|
226 |
+
if($useSetter) {
|
227 |
+
$setData = call_user_func_array(array($mageObject, $rules['setter']), $noWrap ? $getData : array($getData));
|
228 |
+
}
|
229 |
+
}
|
230 |
+
return $mageObject;
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Convert PEAR package to Magento package
|
235 |
+
* @param string $sourceFile path to PEAR .tgz
|
236 |
+
* @param string|false $destFile path to newly-created Magento .tgz, false to specify auto
|
237 |
+
* @return bool
|
238 |
+
*/
|
239 |
+
public function convertPearToMage($sourceFile, $destFile = false)
|
240 |
+
{
|
241 |
+
try {
|
242 |
+
if(!file_exists($sourceFile)) {
|
243 |
+
throw new Exception("File doesn't exist: {$sourceFile}");
|
244 |
+
}
|
245 |
+
$arc = $this->arc();
|
246 |
+
$tempDir = "tmp-".basename($sourceFile).uniqid();
|
247 |
+
$outDir = "out-".basename($sourceFile).uniqid();
|
248 |
+
$outDir = rtrim($outDir, "\\/");
|
249 |
+
Mage_System_Dirs::mkdirStrict($outDir);
|
250 |
+
Mage_System_Dirs::mkdirStrict($tempDir);
|
251 |
+
|
252 |
+
$result = $arc->unpack($sourceFile, $tempDir);
|
253 |
+
if(!$result) {
|
254 |
+
throw new Exception("'{$sourceFile}' was not unpacked");
|
255 |
+
}
|
256 |
+
|
257 |
+
$result = rtrim($result, "\\/");
|
258 |
+
$packageXml = $result . DS . "package.xml";
|
259 |
+
if(!file_exists($packageXml)) {
|
260 |
+
throw new Exception("No package.xml found inside '{$sourceFile}'");
|
261 |
+
}
|
262 |
+
|
263 |
+
$reader = $this->oldPackageReader();
|
264 |
+
$data = file_get_contents($packageXml);
|
265 |
+
|
266 |
+
$pearObject = $reader->parsePackage($data, $packageXml);
|
267 |
+
$mageObject = $this->convertPackageObject($pearObject);
|
268 |
+
if(!$mageObject->validate()) {
|
269 |
+
throw new Exception("Package validation failed.\n". implode("\n", $mageObject->getErrors()));
|
270 |
+
}
|
271 |
+
|
272 |
+
/**
|
273 |
+
* Calculate destination file if false
|
274 |
+
*/
|
275 |
+
if(false === $destFile) {
|
276 |
+
$pathinfo = pathinfo($sourceFile);
|
277 |
+
$destFile = $pathinfo['dirname'] . DS .$pathinfo['filename'].'-converted';
|
278 |
+
if(isset($pathinfo['extension'])) {
|
279 |
+
$destFile .= ".".$pathinfo['extension'];
|
280 |
+
}
|
281 |
+
}
|
282 |
+
|
283 |
+
$target = new Mage_Connect_Package_Target("target.xml");
|
284 |
+
$targets = $target->getTargets();
|
285 |
+
$mageObject->setTarget($target);
|
286 |
+
$validRoles = array_keys($targets);
|
287 |
+
$data = $pearObject->getFilelist();
|
288 |
+
$pathSource = dirname($pearObject->getPackageFile()).DS.$pearObject->getName()."-".$pearObject->getVersion();
|
289 |
+
|
290 |
+
$filesToDo = array();
|
291 |
+
foreach($data as $file =>$row) {
|
292 |
+
$name = $row['name'];
|
293 |
+
$role = $row['role'];
|
294 |
+
if(!in_array($role, $validRoles)) {
|
295 |
+
$role = 'mage';
|
296 |
+
}
|
297 |
+
$baseName = ltrim($targets[$role], "\\/.");
|
298 |
+
$baseName = rtrim($baseName, "\\/");
|
299 |
+
$sourceFile = $pathSource.DS.$name;
|
300 |
+
$targetFile = $outDir . DS . $baseName . DS. $name;
|
301 |
+
if(file_exists($sourceFile)) {
|
302 |
+
Mage_System_Dirs::mkdirStrict(dirname($targetFile));
|
303 |
+
$copy = @copy($sourceFile, $targetFile);
|
304 |
+
if(false === $copy) {
|
305 |
+
throw new Exception("Cannot copy '{$sourceFile}' to '{$targetFile}'");
|
306 |
+
}
|
307 |
+
}
|
308 |
+
$filesToDo[] = array ('name'=> $name, 'role'=>$role);
|
309 |
+
}
|
310 |
+
$cwd = getcwd();
|
311 |
+
@chdir($outDir);
|
312 |
+
foreach($filesToDo as $fileToDo) {
|
313 |
+
$mageObject->addContent($fileToDo['name'], $fileToDo['role']);
|
314 |
+
}
|
315 |
+
$mageObject->save(getcwd());
|
316 |
+
@chdir($cwd);
|
317 |
+
$filename = $outDir. DS . $mageObject->getReleaseFilename().".tgz";
|
318 |
+
if(@file_exists($targetArchive)) {
|
319 |
+
@unlink($targetArchive);
|
320 |
+
}
|
321 |
+
Mage_System_Dirs::mkdirStrict(dirname($destFile));
|
322 |
+
$copy = @copy($filename, $destFile);
|
323 |
+
if(false === $copy) {
|
324 |
+
throw new Exception("Cannot copy '{$filename}' to '{$targetArchive}'");
|
325 |
+
}
|
326 |
+
Mage_System_Dirs::rm($tempDir);
|
327 |
+
Mage_System_Dirs::rm($outDir);
|
328 |
+
|
329 |
+
} catch (Exception $e) {
|
330 |
+
throw $e;
|
331 |
+
}
|
332 |
+
return $destFile;
|
333 |
+
}
|
334 |
+
|
335 |
+
|
336 |
+
|
337 |
+
}
|
lib/Mage/Connect/Frontend.php
ADDED
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
class Mage_Connect_Frontend
|
28 |
+
{
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Silent flag. If set no output is produced to view.
|
32 |
+
* Should be used in derived classes.
|
33 |
+
* @var bool
|
34 |
+
*/
|
35 |
+
protected $_silent = false;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Capture mode. If set command output should be collected
|
39 |
+
* by derived class impplementation
|
40 |
+
* @var bool
|
41 |
+
*/
|
42 |
+
protected $_capture = false;
|
43 |
+
|
44 |
+
|
45 |
+
/**
|
46 |
+
* push/pop variable for capture
|
47 |
+
* @var array
|
48 |
+
*/
|
49 |
+
protected $_captureSaved = array();
|
50 |
+
|
51 |
+
/**
|
52 |
+
* push/pop variable for silent
|
53 |
+
* @var array
|
54 |
+
*/
|
55 |
+
protected $_silentSaved = array();
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Errors list
|
59 |
+
* @var array
|
60 |
+
*/
|
61 |
+
protected $_errors = array();
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Add error to errors list
|
65 |
+
* @param mixed $data
|
66 |
+
* @return void
|
67 |
+
*/
|
68 |
+
public function addError($data)
|
69 |
+
{
|
70 |
+
$this->_errors[] = $data;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Get errors, clear errors list with first param
|
75 |
+
* @param bool $clear
|
76 |
+
* @return array
|
77 |
+
*/
|
78 |
+
public function getErrors($clear = true)
|
79 |
+
{
|
80 |
+
if(!$clear) {
|
81 |
+
return $this->_errors;
|
82 |
+
}
|
83 |
+
$out = $this->_errors;
|
84 |
+
$this->clearErrors();
|
85 |
+
return $out;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Clear errors array
|
90 |
+
* @return void
|
91 |
+
*/
|
92 |
+
public function clearErrors()
|
93 |
+
{
|
94 |
+
$this->_errors = array();
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Are there any errros?
|
99 |
+
* @return bool
|
100 |
+
*/
|
101 |
+
public function hasErrors()
|
102 |
+
{
|
103 |
+
return count($this->_errors) != 0;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Error processing
|
108 |
+
* @param string $command
|
109 |
+
* @param stting $message
|
110 |
+
* @return void
|
111 |
+
*/
|
112 |
+
public function doError($command, $message)
|
113 |
+
{
|
114 |
+
$this->addError(array($command, $message));
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Save capture state
|
119 |
+
* @return Mage_Connect_Frontend
|
120 |
+
*/
|
121 |
+
public function pushCapture()
|
122 |
+
{
|
123 |
+
array_push($this->_captureSaved, $this->_capture);
|
124 |
+
return $this;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Restore capture state
|
129 |
+
* @return Mage_Connect_Frontend
|
130 |
+
*/
|
131 |
+
public function popCapture()
|
132 |
+
{
|
133 |
+
$this->_capture = array_pop($this->_captureSaved);
|
134 |
+
return $this;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Set capture mode
|
139 |
+
* @param bool $arg true by default
|
140 |
+
* @return Mage_Connect_Frontend
|
141 |
+
*/
|
142 |
+
public function setCapture($arg = true)
|
143 |
+
{
|
144 |
+
$this->_capture = $arg;
|
145 |
+
return $this;
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Getter for capture mode
|
150 |
+
* @return bool
|
151 |
+
*/
|
152 |
+
public function isCapture()
|
153 |
+
{
|
154 |
+
return $this->_capture;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Log stub
|
159 |
+
* @param $msg
|
160 |
+
* @return
|
161 |
+
*/
|
162 |
+
public function log($msg)
|
163 |
+
{
|
164 |
+
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Ouptut method
|
169 |
+
* @param array $data
|
170 |
+
* @return void
|
171 |
+
*/
|
172 |
+
public function output($data)
|
173 |
+
{
|
174 |
+
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Get instance of derived class
|
179 |
+
*
|
180 |
+
* @param $class CLI for example will produce Mage_Connect_Frontend_CLI
|
181 |
+
* @return object
|
182 |
+
*/
|
183 |
+
public static function getInstance($class)
|
184 |
+
{
|
185 |
+
$class = __CLASS__."_".$class;
|
186 |
+
return new $class();
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Get output if capture mode set
|
191 |
+
* Clear prevoius if needed
|
192 |
+
* @param bool $clearPrevious
|
193 |
+
* @return mixed
|
194 |
+
*/
|
195 |
+
public function getOutput($clearPrevious = true)
|
196 |
+
{
|
197 |
+
|
198 |
+
}
|
199 |
+
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Save silent mode
|
203 |
+
* @return Mage_Connect_Frontend
|
204 |
+
*/
|
205 |
+
public function pushSilent()
|
206 |
+
{
|
207 |
+
array_push($this->_silentSaved, $this->_silent);
|
208 |
+
return $this;
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Restore silent mode
|
213 |
+
* @return Mage_Connect_Frontend
|
214 |
+
*/
|
215 |
+
public function popSilent()
|
216 |
+
{
|
217 |
+
$this->_silent = array_pop($this->_silentSaved);
|
218 |
+
return $this;
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Set silent mode
|
223 |
+
* @param bool $value
|
224 |
+
* @return Mage_Connect_Frontend
|
225 |
+
*/
|
226 |
+
public function setSilent($value = true)
|
227 |
+
{
|
228 |
+
$this->_silent = (bool) $value;
|
229 |
+
return $this;
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* Is silent mode?
|
234 |
+
* @return bool
|
235 |
+
*/
|
236 |
+
public function isSilent()
|
237 |
+
{
|
238 |
+
return (bool) $this->_silent;
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Method for ask client about rewrite all files.
|
243 |
+
*
|
244 |
+
* @param $string
|
245 |
+
*/
|
246 |
+
public function confirm($string)
|
247 |
+
{
|
248 |
+
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
lib/Mage/Connect/Frontend/CLI.php
ADDED
@@ -0,0 +1,441 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* CLI Frontend implementation
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
|
35 |
+
class Mage_Connect_Frontend_CLI
|
36 |
+
extends Mage_Connect_Frontend
|
37 |
+
{
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Collected output
|
41 |
+
* @var array
|
42 |
+
*/
|
43 |
+
protected $_output = array();
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Output error
|
47 |
+
* @param string $command
|
48 |
+
* @param string $message
|
49 |
+
* @return void
|
50 |
+
*/
|
51 |
+
public function doError($command, $message)
|
52 |
+
{
|
53 |
+
parent::doError($command, $message);
|
54 |
+
$this->writeln("Error: ");
|
55 |
+
$this->writeln("$command: $message");
|
56 |
+
}
|
57 |
+
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Output config help
|
61 |
+
* @param array $data
|
62 |
+
* @return void
|
63 |
+
*/
|
64 |
+
public function outputConfigHelp($data)
|
65 |
+
{
|
66 |
+
foreach($data['data'] as $k=>$v) {
|
67 |
+
if(is_scalar($v)) {
|
68 |
+
$this->writeln($v);
|
69 |
+
} elseif(is_array($v)) {
|
70 |
+
$this->writeln(implode(": ", $v));
|
71 |
+
}
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Output info
|
78 |
+
* @param array $data
|
79 |
+
* @return void
|
80 |
+
*/
|
81 |
+
public function outputRemoteInfo($data)
|
82 |
+
{
|
83 |
+
if(!is_array($data['releases'])) {
|
84 |
+
return;
|
85 |
+
}
|
86 |
+
foreach ($data['releases'] as $r) {
|
87 |
+
$this->writeln(implode(" ", $r));
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
|
92 |
+
public function detectMethodByType($type)
|
93 |
+
{
|
94 |
+
$defaultMethod = "output";
|
95 |
+
$methodMap = array(
|
96 |
+
'list-upgrades'=> 'outputUpgrades',
|
97 |
+
'list-available' => 'outputChannelsPackages',
|
98 |
+
'list-installed' => 'writeInstalledList',
|
99 |
+
'package-dependencies' => 'outputPackageDeps',
|
100 |
+
'list-files' => 'outputPackageContents',
|
101 |
+
'config-help' => 'outputConfigHelp',
|
102 |
+
'info' => 'outputRemoteInfo',
|
103 |
+
'config-show' => 'outputConfig',
|
104 |
+
'install' => 'outputInstallResult',
|
105 |
+
'install-file' => 'outputInstallResult',
|
106 |
+
'upgrade' => 'outputInstallResult',
|
107 |
+
'upgrade-all' => 'outputInstallResult',
|
108 |
+
'uninstall' => 'outputDeleted',
|
109 |
+
'list-channels' => 'outputListChannels',
|
110 |
+
);
|
111 |
+
if(isset($methodMap[$type])) {
|
112 |
+
return $methodMap[$type];
|
113 |
+
}
|
114 |
+
return $defaultMethod;
|
115 |
+
}
|
116 |
+
|
117 |
+
|
118 |
+
public function outputDeleted($data)
|
119 |
+
{
|
120 |
+
if(!count($data['data'])) {
|
121 |
+
return;
|
122 |
+
}
|
123 |
+
$this->writeln($data['title']);
|
124 |
+
foreach($data['data'] as $row) {
|
125 |
+
$this->writeln("$row[0]/$row[1]");
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
public function outputListChannels($data)
|
130 |
+
{
|
131 |
+
$this->writeln($data['title']);
|
132 |
+
|
133 |
+
$channels =& $data['data'][Mage_Connect_Singleconfig::K_CHAN];
|
134 |
+
foreach($channels as $name => $v) {
|
135 |
+
$this->writeln("$name: {$v[Mage_Connect_Singleconfig::K_URI]}");
|
136 |
+
}
|
137 |
+
$aliases =& $data['data'][Mage_Connect_Singleconfig::K_CHAN_ALIAS];
|
138 |
+
if(count($aliases)) {
|
139 |
+
$this->writeln();
|
140 |
+
$this->writeln($data['title_aliases']);
|
141 |
+
foreach($aliases as $k=>$v) {
|
142 |
+
$this->writeln("$k => $v");
|
143 |
+
}
|
144 |
+
}
|
145 |
+
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Output install result
|
150 |
+
* @param array $data
|
151 |
+
* @return void
|
152 |
+
*/
|
153 |
+
public function outputInstallResult($data)
|
154 |
+
{
|
155 |
+
if(isset($data['title'])) {
|
156 |
+
$title = trim($data['title'])." ";
|
157 |
+
} else {
|
158 |
+
$title = '';
|
159 |
+
}
|
160 |
+
foreach($data['assoc'] as $row) {
|
161 |
+
$this->printf("%s%s/%s %s\n", $title, $row['channel'], $row['name'], $row['version']);
|
162 |
+
}
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Ouptut package contents
|
167 |
+
* @param array $data
|
168 |
+
* @return void
|
169 |
+
*/
|
170 |
+
public function outputPackageContents($data)
|
171 |
+
{
|
172 |
+
$this->writeln($data['title']);
|
173 |
+
foreach($data['data'] as $file) {
|
174 |
+
$this->writeln($file);
|
175 |
+
}
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Output package dependencies
|
180 |
+
* @param $data
|
181 |
+
* @return void
|
182 |
+
*/
|
183 |
+
public function outputPackageDeps($data)
|
184 |
+
{
|
185 |
+
$title = $data['title'];
|
186 |
+
$this->writeln($title);
|
187 |
+
foreach($data['data'] as $package) {
|
188 |
+
$this->printf("%-20s %-20s %-20s %-20s\n", $package['channel'], $package['name'], $package['min'], $package['max']);
|
189 |
+
}
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Ouptut channel packages
|
194 |
+
* @param $data
|
195 |
+
* @return unknown_type
|
196 |
+
*/
|
197 |
+
public function outputChannelsPackages($data)
|
198 |
+
{
|
199 |
+
foreach($data['data'] as $channelInfo) {
|
200 |
+
$title =& $channelInfo['title'];
|
201 |
+
$packages =& $channelInfo['packages'];
|
202 |
+
$this->writeln($title);
|
203 |
+
foreach($packages as $name=>$package) {
|
204 |
+
$releases =& $package['releases'];
|
205 |
+
$tmp = array();
|
206 |
+
foreach($releases as $ver=>$state) {
|
207 |
+
$tmp[] = "$ver $state";
|
208 |
+
}
|
209 |
+
$tmp = implode(',',$tmp);
|
210 |
+
$this->writeln($name.": ".$tmp);
|
211 |
+
}
|
212 |
+
}
|
213 |
+
}
|
214 |
+
|
215 |
+
|
216 |
+
/**
|
217 |
+
* Make output
|
218 |
+
*
|
219 |
+
* @param array $data
|
220 |
+
* @return void
|
221 |
+
*/
|
222 |
+
|
223 |
+
public function output($data)
|
224 |
+
{
|
225 |
+
$capture = $this->isCapture();
|
226 |
+
if($capture) {
|
227 |
+
$this->_output[] = $data;
|
228 |
+
return;
|
229 |
+
}
|
230 |
+
|
231 |
+
if(is_array($data)) {
|
232 |
+
foreach($data as $type=>$params) {
|
233 |
+
$method = $this->detectMethodByType($type);
|
234 |
+
if($method) {
|
235 |
+
$this->$method($params);
|
236 |
+
} else {
|
237 |
+
$this->writeln(__METHOD__." handler not found for {$type}");
|
238 |
+
}
|
239 |
+
}
|
240 |
+
} else {
|
241 |
+
$this->writeln($data);
|
242 |
+
}
|
243 |
+
}
|
244 |
+
|
245 |
+
|
246 |
+
/**
|
247 |
+
* Detailed package info
|
248 |
+
* @param Mage_Connect_Package $package
|
249 |
+
* @return void
|
250 |
+
*/
|
251 |
+
public function outputPackage($package)
|
252 |
+
{
|
253 |
+
$fields = array(
|
254 |
+
'Name'=>'name',
|
255 |
+
'Version'=>'version',
|
256 |
+
'Stability'=>'stability',
|
257 |
+
'Description' => 'description',
|
258 |
+
'Date' => 'date',
|
259 |
+
'Authors' => 'authors',
|
260 |
+
);
|
261 |
+
|
262 |
+
foreach($fields as $title => $fld) {
|
263 |
+
$method = "get".ucfirst($fld);
|
264 |
+
$data = $package->$method();
|
265 |
+
if(empty($data)) {
|
266 |
+
continue;
|
267 |
+
}
|
268 |
+
$this->write($title.": ");
|
269 |
+
if(is_array($data)) {
|
270 |
+
$this->write(print_r($data,true));
|
271 |
+
} else {
|
272 |
+
$this->write($data);
|
273 |
+
}
|
274 |
+
$this->writeln('');
|
275 |
+
}
|
276 |
+
}
|
277 |
+
|
278 |
+
|
279 |
+
/**
|
280 |
+
* Write channels list
|
281 |
+
* @param array $data
|
282 |
+
* @return void
|
283 |
+
*/
|
284 |
+
public function writeChannelsList($data)
|
285 |
+
{
|
286 |
+
$this->writeln("Channels available: ");
|
287 |
+
$this->writeln("===================");
|
288 |
+
$out = $data['byName'];
|
289 |
+
ksort($out);
|
290 |
+
foreach($out as $k=>$v) {
|
291 |
+
$this->printf ("%-20s %-20s\n", $k, $v);
|
292 |
+
}
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* Write installed list
|
297 |
+
* @param array $data
|
298 |
+
* @return void
|
299 |
+
*/
|
300 |
+
public function writeInstalledList($data)
|
301 |
+
{
|
302 |
+
$totalCount = 0;
|
303 |
+
foreach($data['data'] as $channel=>$packages) {
|
304 |
+
$title = sprintf($data['channel-title'], $channel);
|
305 |
+
$c = count($packages);
|
306 |
+
$totalCount += $c;
|
307 |
+
if(!$c) {
|
308 |
+
continue;
|
309 |
+
}
|
310 |
+
$this->writeln($title);
|
311 |
+
foreach($packages as $name=>$row) {
|
312 |
+
$this->printf("%-20s %-20s\n", $name, $row['version']." ".$row['stability']);
|
313 |
+
}
|
314 |
+
}
|
315 |
+
if($totalCount === 0) {
|
316 |
+
$this->writeln("No installed packages");
|
317 |
+
}
|
318 |
+
}
|
319 |
+
|
320 |
+
/**
|
321 |
+
* Output commands list
|
322 |
+
* @param array $data
|
323 |
+
* @return void
|
324 |
+
*/
|
325 |
+
public function outputCommandList($data)
|
326 |
+
{
|
327 |
+
$this->writeln("Connect commands available:");
|
328 |
+
$this->writeln("===========================");
|
329 |
+
foreach ($data as $k=>$v) {
|
330 |
+
$this->printf ("%-20s %-20s\n", $k, $v['summary']);
|
331 |
+
}
|
332 |
+
}
|
333 |
+
|
334 |
+
/**
|
335 |
+
* Output config
|
336 |
+
* @param array $data
|
337 |
+
* @return void
|
338 |
+
*/
|
339 |
+
public function outputConfig($data)
|
340 |
+
{
|
341 |
+
foreach($data['data'] as $name=>$row) {
|
342 |
+
$value = $row['value'] === '' ? "<not set>" : strval($row['value']);
|
343 |
+
$this->printf("%-30s %-20s %-20s\n", $row['prompt'], $name, $value);
|
344 |
+
}
|
345 |
+
}
|
346 |
+
|
347 |
+
/**
|
348 |
+
* Output config variable
|
349 |
+
* @param string $key
|
350 |
+
* @param string $value
|
351 |
+
* @return void
|
352 |
+
*/
|
353 |
+
public function outputConfigVariable($key, $value)
|
354 |
+
{
|
355 |
+
if($value === '') {
|
356 |
+
$value = '<not set>';
|
357 |
+
}
|
358 |
+
$this->writeln("Config variable '{$key}': {$value}");
|
359 |
+
}
|
360 |
+
|
361 |
+
/**
|
362 |
+
* Write data and "\n" afterwards
|
363 |
+
* @param string $data
|
364 |
+
* @return void
|
365 |
+
*/
|
366 |
+
public function writeln($data = '')
|
367 |
+
{
|
368 |
+
$this->write($data."\n");
|
369 |
+
}
|
370 |
+
|
371 |
+
|
372 |
+
/**
|
373 |
+
* get output, clear if needed
|
374 |
+
*
|
375 |
+
* @param bool $clearPrevoius optional, true by default
|
376 |
+
* @return array
|
377 |
+
*/
|
378 |
+
public function getOutput($clearPrevious = true)
|
379 |
+
{
|
380 |
+
$out = $this->_output;
|
381 |
+
if($clearPrevious) {
|
382 |
+
$this->_output = array();
|
383 |
+
}
|
384 |
+
return $out;
|
385 |
+
}
|
386 |
+
|
387 |
+
/**
|
388 |
+
* Write data to console
|
389 |
+
* @param string $data
|
390 |
+
* @return void
|
391 |
+
*/
|
392 |
+
public function write($data)
|
393 |
+
{
|
394 |
+
if($this->isSilent()) {
|
395 |
+
return;
|
396 |
+
}
|
397 |
+
print $data;
|
398 |
+
}
|
399 |
+
|
400 |
+
/**
|
401 |
+
* Output printf-stlye formatted string and args
|
402 |
+
* @return void
|
403 |
+
*/
|
404 |
+
public function printf()
|
405 |
+
{
|
406 |
+
$args = func_get_args();
|
407 |
+
$this->write(call_user_func_array('sprintf', $args));
|
408 |
+
}
|
409 |
+
|
410 |
+
/**
|
411 |
+
* Readline from console
|
412 |
+
* @return string
|
413 |
+
*/
|
414 |
+
public function readln()
|
415 |
+
{
|
416 |
+
$out = "";
|
417 |
+
$key = fgetc(STDIN);
|
418 |
+
while ($key!="\n") {
|
419 |
+
$out.= $key;
|
420 |
+
$key = fread(STDIN, 1);
|
421 |
+
}
|
422 |
+
return $out;
|
423 |
+
}
|
424 |
+
|
425 |
+
/**
|
426 |
+
* Output upgrades
|
427 |
+
* @param array $data
|
428 |
+
* @return void
|
429 |
+
*/
|
430 |
+
public function outputUpgrades($data)
|
431 |
+
{
|
432 |
+
foreach($data['data'] as $chan => $packages) {
|
433 |
+
$this->writeln("Updates for ".$chan.": ");
|
434 |
+
foreach($packages as $name => $data) {
|
435 |
+
$this->writeln(" $name: {$data['from']} => {$data['to']}");
|
436 |
+
}
|
437 |
+
}
|
438 |
+
}
|
439 |
+
|
440 |
+
}
|
441 |
+
|
lib/Mage/Connect/Ftp.php
ADDED
@@ -0,0 +1,494 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with remote FTP server
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Connect_Ftp
|
35 |
+
{
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Connection object
|
39 |
+
* @var resource
|
40 |
+
*/
|
41 |
+
protected $_conn = false;
|
42 |
+
|
43 |
+
public function __construct()
|
44 |
+
{
|
45 |
+
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Check connected, throw exception if not
|
50 |
+
* @throws Exception
|
51 |
+
* @return void
|
52 |
+
*/
|
53 |
+
protected function checkConnected()
|
54 |
+
{
|
55 |
+
if(!$this->_conn) {
|
56 |
+
throw new Exception(__CLASS__." - no connection established with server");
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* ftp_mkdir wrapper
|
62 |
+
* @param stin$name
|
63 |
+
* @return unknown_type
|
64 |
+
*/
|
65 |
+
public function mdkir($name)
|
66 |
+
{
|
67 |
+
$this->checkConnected();
|
68 |
+
return @ftp_mkdir($this->_conn, $name);
|
69 |
+
}
|
70 |
+
|
71 |
+
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Make dir recursive
|
75 |
+
* @param string $path
|
76 |
+
* @param int $mode
|
77 |
+
*/
|
78 |
+
public function mkdirRecursive($path, $mode = 0777)
|
79 |
+
{
|
80 |
+
$this->checkConnected();
|
81 |
+
$dir = split("/", $path);
|
82 |
+
$path= "";
|
83 |
+
$ret = true;
|
84 |
+
for ($i=0; $i < count($dir); $i++) {
|
85 |
+
$path .= "/" .$dir[$i];
|
86 |
+
if(!@ftp_chdir($this->_conn, $path)) {
|
87 |
+
@ftp_chdir($this->_conn,"/");
|
88 |
+
if(!@ftp_mkdir($this->_conn,$path)) {
|
89 |
+
$ret=false;
|
90 |
+
break;
|
91 |
+
} else {
|
92 |
+
@ftp_chmod($this->_conn, $mode, $path);
|
93 |
+
}
|
94 |
+
}
|
95 |
+
}
|
96 |
+
return $ret;
|
97 |
+
}
|
98 |
+
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Try to login to server
|
102 |
+
* @param string $login
|
103 |
+
* @param string $password
|
104 |
+
* @throws Exception on invalid login credentials
|
105 |
+
* @return bool
|
106 |
+
*/
|
107 |
+
public function login($login = "anonymous", $password = "test@gmail.com")
|
108 |
+
{
|
109 |
+
$this->checkConnected();
|
110 |
+
$res = @ftp_login($this->_conn, $login, $password);
|
111 |
+
if(!$res) {
|
112 |
+
throw new Exception("Invalid login credentials");
|
113 |
+
}
|
114 |
+
return $res;
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Validate connection string
|
119 |
+
* @param string $string
|
120 |
+
* @throws Exception
|
121 |
+
* @return string
|
122 |
+
*/
|
123 |
+
public function validateConnectionString($string)
|
124 |
+
{
|
125 |
+
$data = @parse_url($string);
|
126 |
+
if(false === $data) {
|
127 |
+
throw new Exception("Connection string invalid: '{$string}'");
|
128 |
+
}
|
129 |
+
if($data['scheme'] != 'ftp') {
|
130 |
+
throw new Exception("Support for scheme unsupported: '{$data['scheme']}'");
|
131 |
+
}
|
132 |
+
return $data;
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Connect to server using connect string
|
137 |
+
* Connection string: ftp://user:pass@server:port/path
|
138 |
+
* user,pass,port,path are optional parts
|
139 |
+
* @param string $string
|
140 |
+
*
|
141 |
+
* @param $timeout
|
142 |
+
* @return unknown_type
|
143 |
+
*/
|
144 |
+
public function connect($string, $timeout = 900)
|
145 |
+
{
|
146 |
+
$params = $this->validateConnectionString($string);
|
147 |
+
$port = isset($params['port']) ? intval($params['port']) : 21;
|
148 |
+
|
149 |
+
$this->_conn = ftp_connect($params['host'], $port, $timeout);
|
150 |
+
|
151 |
+
if(!$this->_conn) {
|
152 |
+
throw new Exception("Cannot connect to host: {$params['host']}");
|
153 |
+
}
|
154 |
+
if(isset($params['user']) && isset($params['pass'])) {
|
155 |
+
$this->login($params['user'], $params['pass']);
|
156 |
+
} else {
|
157 |
+
$this->login();
|
158 |
+
}
|
159 |
+
if(isset($params['path'])) {
|
160 |
+
if(!$this->chdir($params['path'])) {
|
161 |
+
throw new Exception ("Cannot chdir after login to: {$params['path']}");
|
162 |
+
}
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* ftp_fput wrapper
|
168 |
+
* @param string $remoteFile
|
169 |
+
* @param resource $handle
|
170 |
+
* @param int $mode FTP_BINARY | FTP_ASCII
|
171 |
+
* @param int $startPos
|
172 |
+
* @return bool
|
173 |
+
*/
|
174 |
+
|
175 |
+
public function fput($remoteFile, $handle, $mode = FTP_BINARY, $startPos = 0)
|
176 |
+
{
|
177 |
+
$this->checkConnected();
|
178 |
+
return @ftp_fput($this->_conn, $remoteFile, $handle, $mode, $startPos);
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* ftp_put wrapper
|
183 |
+
* @param string $remoteFile
|
184 |
+
* @param string $localFile
|
185 |
+
* @param int $mode FTP_BINARY | FTP_ASCII
|
186 |
+
* @param int $startPos
|
187 |
+
* @return bool
|
188 |
+
*/
|
189 |
+
public function put($remoteFile, $localFile, $mode = FTP_BINARY, $startPos = 0)
|
190 |
+
{
|
191 |
+
$this->checkConnected();
|
192 |
+
return ftp_put($this->_conn, $remoteFile, $localFile, $mode, $startPos);
|
193 |
+
}
|
194 |
+
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Get current working directory
|
198 |
+
* @return mixed
|
199 |
+
*/
|
200 |
+
public function getcwd()
|
201 |
+
{
|
202 |
+
$d = $this->raw("pwd");
|
203 |
+
$data = explode(" ", $d[0], 3);
|
204 |
+
if(empty($data[1])) {
|
205 |
+
return false;
|
206 |
+
}
|
207 |
+
if(intval($data[0]) != 257) {
|
208 |
+
return false;
|
209 |
+
}
|
210 |
+
$out = trim($data[1], '"');
|
211 |
+
if($out !== "/") {
|
212 |
+
$out = rtrim($out, "/");
|
213 |
+
}
|
214 |
+
return $out;
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* ftp_raw wrapper
|
219 |
+
* @param string $cmd
|
220 |
+
* @return mixed
|
221 |
+
*/
|
222 |
+
public function raw($cmd)
|
223 |
+
{
|
224 |
+
$this->checkConnected();
|
225 |
+
return @ftp_raw($this->_conn, $cmd);
|
226 |
+
}
|
227 |
+
|
228 |
+
|
229 |
+
/**
|
230 |
+
* Upload local file to remote
|
231 |
+
*
|
232 |
+
* Can be used for relative and absoulte remote paths
|
233 |
+
* Relative: use chdir before calling this
|
234 |
+
*
|
235 |
+
* @param srting $remote
|
236 |
+
* @param string $local
|
237 |
+
* @param int $dirMode
|
238 |
+
* @param int $ftpMode
|
239 |
+
* @return unknown_type
|
240 |
+
*/
|
241 |
+
public function upload($remote, $local, $dirMode = 0777, $ftpMode = FTP_BINARY)
|
242 |
+
{
|
243 |
+
$this->checkConnected();
|
244 |
+
|
245 |
+
if(!file_exists($local)) {
|
246 |
+
throw new Exception("Local file doesn't exist: {$localFile}");
|
247 |
+
}
|
248 |
+
if(!is_readable($local)) {
|
249 |
+
throw new Exception("Local file is not readable: {$localFile}");
|
250 |
+
}
|
251 |
+
if(is_dir($local)) {
|
252 |
+
throw new Exception("Directory given instead of file: {$localFile}");
|
253 |
+
}
|
254 |
+
|
255 |
+
$globalPathMode = substr($remote, 0, 1) == "/";
|
256 |
+
$dirname = dirname($remote);
|
257 |
+
$cwd = $this->getcwd();
|
258 |
+
if(false === $cwd) {
|
259 |
+
throw new Exception("Server returns something awful on PWD command");
|
260 |
+
}
|
261 |
+
|
262 |
+
if(!$globalPathMode) {
|
263 |
+
$dirname = $cwd."/".$dirname;
|
264 |
+
$remote = $cwd."/".$remote;
|
265 |
+
}
|
266 |
+
$res = $this->mkdirRecursive($dirname, $dirMode);
|
267 |
+
$this->chdir($cwd);
|
268 |
+
|
269 |
+
if(!$res) {
|
270 |
+
return false;
|
271 |
+
}
|
272 |
+
return $this->put($remote, $local, $ftpMode);
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* Download remote file to local machine
|
277 |
+
* @param string $remote
|
278 |
+
* @param string $local
|
279 |
+
* @param int $ftpMode FTP_BINARY|FTP_ASCII
|
280 |
+
* @return bool
|
281 |
+
*/
|
282 |
+
public function download($remote, $local, $ftpMode = FTP_BINARY)
|
283 |
+
{
|
284 |
+
$this->checkConnected();
|
285 |
+
return $this->get($local, $remote, $ftpMode);
|
286 |
+
}
|
287 |
+
|
288 |
+
|
289 |
+
/**
|
290 |
+
* ftp_pasv wrapper
|
291 |
+
* @param bool $pasv
|
292 |
+
* @return bool
|
293 |
+
*/
|
294 |
+
public function pasv($pasv)
|
295 |
+
{
|
296 |
+
$this->checkConnected();
|
297 |
+
return @ftp_pasv($this->_conn, (bool) $pasv);
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* Close FTP connection
|
302 |
+
* @return void
|
303 |
+
*/
|
304 |
+
public function close()
|
305 |
+
{
|
306 |
+
if($this->_conn) {
|
307 |
+
@ftp_close($this->_conn);
|
308 |
+
}
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* ftp_chmod wrapper
|
313 |
+
* @param $mode
|
314 |
+
* @param $remoteFile
|
315 |
+
* @return bool
|
316 |
+
*/
|
317 |
+
public function chmod($mode, $remoteFile)
|
318 |
+
{
|
319 |
+
$this->checkConnected();
|
320 |
+
return @ftp_chmod($this->_conn, $mode, $remoteFile);
|
321 |
+
}
|
322 |
+
|
323 |
+
/**
|
324 |
+
* ftp_chdir wrapper
|
325 |
+
* @param string $dir
|
326 |
+
* @return bool
|
327 |
+
*/
|
328 |
+
public function chdir($dir)
|
329 |
+
{
|
330 |
+
$this->checkConnected();
|
331 |
+
return @ftp_chdir($this->_conn, $dir);
|
332 |
+
}
|
333 |
+
|
334 |
+
/**
|
335 |
+
* ftp_cdup wrapper
|
336 |
+
* @return bool
|
337 |
+
*/
|
338 |
+
public function cdup()
|
339 |
+
{
|
340 |
+
$this->checkConnected();
|
341 |
+
return @ftp_cdup($this->_conn);
|
342 |
+
}
|
343 |
+
|
344 |
+
/**
|
345 |
+
* ftp_get wrapper
|
346 |
+
* @param string $localFile
|
347 |
+
* @param string $remoteFile
|
348 |
+
* @param int $fileMode FTP_BINARY | FTP_ASCII
|
349 |
+
* @param int $resumeOffset
|
350 |
+
* @return bool
|
351 |
+
*/
|
352 |
+
public function get($localFile, $remoteFile, $fileMode = FTP_BINARY, $resumeOffset = 0)
|
353 |
+
{
|
354 |
+
$remoteFile = $this->correctFilePath($remoteFile);
|
355 |
+
$this->checkConnected();
|
356 |
+
return @ftp_get($this->_conn, $localFile, $remoteFile, $fileMode, $resumeOffset);
|
357 |
+
}
|
358 |
+
|
359 |
+
/**
|
360 |
+
* ftp_nlist wrapper
|
361 |
+
* @param string $dir
|
362 |
+
* @return bool
|
363 |
+
*/
|
364 |
+
public function nlist($dir = "/")
|
365 |
+
{
|
366 |
+
$this->checkConnected();
|
367 |
+
$dir = $this->correctFilePath($dir);
|
368 |
+
return @ftp_nlist($this->_conn, $dir);
|
369 |
+
}
|
370 |
+
|
371 |
+
/**
|
372 |
+
* ftp_rawlist wrapper
|
373 |
+
* @param string $dir
|
374 |
+
* @param bool $recursive
|
375 |
+
* @return mixed
|
376 |
+
*/
|
377 |
+
public function rawlist( $dir = "/", $recursive = false )
|
378 |
+
{
|
379 |
+
$this->checkConnected();
|
380 |
+
$dir = $this->correctFilePath($dir);
|
381 |
+
return @ftp_rawlist($this->_conn, $dir, $recursive);
|
382 |
+
}
|
383 |
+
|
384 |
+
|
385 |
+
/**
|
386 |
+
* Convert byte count to float KB/MB format
|
387 |
+
* @param int $bytes
|
388 |
+
* @return string
|
389 |
+
*/
|
390 |
+
public static function byteconvert($bytes)
|
391 |
+
{
|
392 |
+
$symbol = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
|
393 |
+
$exp = floor( log($bytes) / log(1024) );
|
394 |
+
return sprintf( '%.2f ' . $symbol[ $exp ], ($bytes / pow(1024, floor($exp))) );
|
395 |
+
}
|
396 |
+
|
397 |
+
/**
|
398 |
+
* Chmod string "-rwxrwxrwx" to "777" converter
|
399 |
+
* @param string $chmod
|
400 |
+
* @return string
|
401 |
+
*/
|
402 |
+
public static function chmodnum($chmod)
|
403 |
+
{
|
404 |
+
$trans = array('-' => '0', 'r' => '4', 'w' => '2', 'x' => '1');
|
405 |
+
$chmod = substr(strtr($chmod, $trans), 1);
|
406 |
+
$array = str_split($chmod, 3);
|
407 |
+
return array_sum(str_split($array[0])) . array_sum(str_split($array[1])) . array_sum(str_split($array[2]));
|
408 |
+
}
|
409 |
+
|
410 |
+
|
411 |
+
public function fileExists($path, $excludeIfIsDir = true)
|
412 |
+
{
|
413 |
+
$path = $this->correctFilePath($path);
|
414 |
+
$globalPathMode = substr($path, 0, 1) == "/";
|
415 |
+
|
416 |
+
$file = basename($path);
|
417 |
+
$dir = $globalPathMode ? dirname($path) : $this->getcwd()."/".$path;
|
418 |
+
$data = $this->ls($dir);
|
419 |
+
foreach($data as $row) {
|
420 |
+
if($file == $row['name']) {
|
421 |
+
if($excludeIfIsDir && $row['dir']) {
|
422 |
+
continue;
|
423 |
+
}
|
424 |
+
return true;
|
425 |
+
}
|
426 |
+
}
|
427 |
+
return false;
|
428 |
+
}
|
429 |
+
|
430 |
+
|
431 |
+
/**
|
432 |
+
* Get directory contents in PHP array
|
433 |
+
* @param string $dir
|
434 |
+
* @param bool $recursive
|
435 |
+
* @return array
|
436 |
+
*/
|
437 |
+
public function ls($dir = "/", $recursive = false)
|
438 |
+
{
|
439 |
+
$dir= $this->correctFilePath($dir);
|
440 |
+
$rawfiles = (array) $this->rawlist($dir, $recursive);
|
441 |
+
$structure = array();
|
442 |
+
$arraypointer = &$structure;
|
443 |
+
foreach ($rawfiles as $rawfile) {
|
444 |
+
if ($rawfile[0] == '/') {
|
445 |
+
$paths = array_slice(explode('/', str_replace(':', '', $rawfile)), 1);
|
446 |
+
$arraypointer = &$structure;
|
447 |
+
foreach ($paths as $path) {
|
448 |
+
foreach ($arraypointer as $i => $file) {
|
449 |
+
if ($file['name'] == $path) {
|
450 |
+
$arraypointer = &$arraypointer[ $i ]['children'];
|
451 |
+
break;
|
452 |
+
}
|
453 |
+
}
|
454 |
+
}
|
455 |
+
} elseif(!empty($rawfile)) {
|
456 |
+
$info = preg_split("/[\s]+/", $rawfile, 9);
|
457 |
+
$arraypointer[] = array(
|
458 |
+
'name' => $info[8],
|
459 |
+
'dir' => $info[0]{0} == 'd',
|
460 |
+
'size' => (int) $info[4],
|
461 |
+
'chmod' => self::chmodnum($info[0]),
|
462 |
+
'rawdata' => $info,
|
463 |
+
'raw' => $rawfile
|
464 |
+
);
|
465 |
+
}
|
466 |
+
}
|
467 |
+
return $structure;
|
468 |
+
}
|
469 |
+
|
470 |
+
|
471 |
+
/**
|
472 |
+
* Correct file path
|
473 |
+
* @param $str
|
474 |
+
* @return string
|
475 |
+
*/
|
476 |
+
public function correctFilePath($str)
|
477 |
+
{
|
478 |
+
$str = str_replace("\\", "/", $str);
|
479 |
+
$str = preg_replace("/^.\//", "", $str);
|
480 |
+
return $str;
|
481 |
+
}
|
482 |
+
|
483 |
+
public function delete($file)
|
484 |
+
{
|
485 |
+
$this->checkConnected();
|
486 |
+
$file = $this->correctFilePath($file);
|
487 |
+
return @ftp_delete($this->_conn, $file);
|
488 |
+
}
|
489 |
+
|
490 |
+
|
491 |
+
|
492 |
+
|
493 |
+
|
494 |
+
}
|
lib/Mage/Connect/Loader.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class for loader which using in the Rest
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Connect_Loader
|
35 |
+
{
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Factory for HTTP client
|
39 |
+
* @param string/false $protocol 'curl'/'socket' or false for auto-detect
|
40 |
+
* @return Mage_HTTP_Client/Mage_Connect_Loader_Ftp
|
41 |
+
*/
|
42 |
+
public static function getInstance($protocol='')
|
43 |
+
{
|
44 |
+
if ($protocol == 'ftp') {
|
45 |
+
return new Mage_Connect_Loader_Ftp();
|
46 |
+
} else {
|
47 |
+
return Mage_HTTP_Client::getInstance();
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
}
|
lib/Mage/Connect/Loader/Ftp.php
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class for ftp loader which using in the Rest
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Connect_Loader_Ftp
|
35 |
+
{
|
36 |
+
|
37 |
+
const TEMPORARY_DIR = 'var/package/tmp';
|
38 |
+
|
39 |
+
const FTP_USER = 'magconnect';
|
40 |
+
|
41 |
+
const FTP_PASS = '4SyTUxPts0o2';
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Object of Ftp
|
45 |
+
*
|
46 |
+
* @var Mage_Connect_Ftp
|
47 |
+
*/
|
48 |
+
protected $_ftp = null;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Response body
|
52 |
+
* @var string
|
53 |
+
*/
|
54 |
+
protected $_responseBody = '';
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Response status
|
58 |
+
* @var int
|
59 |
+
*/
|
60 |
+
protected $_responseStatus = 0;
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Constructor
|
64 |
+
*/
|
65 |
+
public function __construct()
|
66 |
+
{
|
67 |
+
$this->_ftp = new Mage_Connect_Ftp();
|
68 |
+
}
|
69 |
+
|
70 |
+
public function getFtp()
|
71 |
+
{
|
72 |
+
return $this->_ftp;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Retrieve file from URI
|
77 |
+
*
|
78 |
+
* @param mixed $uri
|
79 |
+
* @return bool
|
80 |
+
*/
|
81 |
+
public function get($uri)
|
82 |
+
{
|
83 |
+
$remoteFile = basename($uri);
|
84 |
+
$uri = dirname($uri);
|
85 |
+
$uri = str_replace('http://', '', $uri);
|
86 |
+
$uri = str_replace('ftp://', '', $uri);
|
87 |
+
$uri = self::FTP_USER.":".self::FTP_PASS."@".$uri;
|
88 |
+
$this->getFtp()->connect("ftp://".$uri);
|
89 |
+
$this->getFtp()->pasv(true);
|
90 |
+
$localFile = self::TEMPORARY_DIR.DS.time().".xml";
|
91 |
+
|
92 |
+
if ($this->getFtp()->get($localFile, $remoteFile)) {
|
93 |
+
$this->_responseBody = file_get_contents($localFile);
|
94 |
+
$this->_responseStatus = 200;
|
95 |
+
}
|
96 |
+
@unlink($localFile);
|
97 |
+
$this->getFtp()->close();
|
98 |
+
return $out;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Get response status code
|
103 |
+
*
|
104 |
+
* @return string
|
105 |
+
*/
|
106 |
+
public function getStatus()
|
107 |
+
{
|
108 |
+
return $this->_responseStatus;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* put your comment there...
|
113 |
+
*
|
114 |
+
* @return string
|
115 |
+
*/
|
116 |
+
public function getBody()
|
117 |
+
{
|
118 |
+
return $this->_responseBody;
|
119 |
+
}
|
120 |
+
|
121 |
+
}
|
lib/Mage/Connect/Package.php
ADDED
@@ -0,0 +1,1486 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with Magento Connect packages
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Connect_Package
|
35 |
+
{
|
36 |
+
/*
|
37 |
+
* Current version of magento connect package format
|
38 |
+
*/
|
39 |
+
const PACKAGE_VERSION_2X = '2';
|
40 |
+
|
41 |
+
/*
|
42 |
+
* Previous version of magento connect package format
|
43 |
+
*/
|
44 |
+
const PACKAGE_VERSION_1X = '1';
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Contain SimpleXMLElement for composing document.
|
48 |
+
*
|
49 |
+
* @var SimpleXMLElement
|
50 |
+
*/
|
51 |
+
protected $_packageXml;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Internal cache
|
55 |
+
*
|
56 |
+
* @var array
|
57 |
+
*/
|
58 |
+
protected $_authors;
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Internal cache
|
62 |
+
*
|
63 |
+
* @var array
|
64 |
+
*/
|
65 |
+
protected $_contents;
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Internal cache
|
69 |
+
*
|
70 |
+
* @var array
|
71 |
+
*/
|
72 |
+
protected $_hashContents;
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Internal cache
|
76 |
+
*
|
77 |
+
* @var array
|
78 |
+
*/
|
79 |
+
protected $_compatible;
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Internal cache
|
83 |
+
*
|
84 |
+
* @var array
|
85 |
+
*/
|
86 |
+
protected $_dependencyPhpExtensions;
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Internal cache
|
90 |
+
*
|
91 |
+
* @var array
|
92 |
+
*/
|
93 |
+
protected $_dependencyPackages;
|
94 |
+
|
95 |
+
/**
|
96 |
+
* A helper object that can read from a package archive
|
97 |
+
*
|
98 |
+
* @var Mage_Connect_Package_Reader
|
99 |
+
*/
|
100 |
+
protected $_reader;
|
101 |
+
|
102 |
+
/**
|
103 |
+
* A helper object that can create and write to a package archive
|
104 |
+
*
|
105 |
+
* @var Mage_Connect_Package_Writer
|
106 |
+
*/
|
107 |
+
protected $_writer;
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Validator object
|
111 |
+
*
|
112 |
+
* @var Mage_Connect_Validator
|
113 |
+
*/
|
114 |
+
protected $_validator = null;
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Validation errors
|
118 |
+
*
|
119 |
+
* @var array
|
120 |
+
*/
|
121 |
+
protected $_validationErrors = array();
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Object with target
|
125 |
+
*
|
126 |
+
* @var Mage_Connect_Package_Target
|
127 |
+
*/
|
128 |
+
protected $_target = null;
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Creates a package object (empty, or from existing archive, or from package definition xml)
|
132 |
+
*
|
133 |
+
* @param null|string|resource $source
|
134 |
+
*/
|
135 |
+
public function __construct($source=null)
|
136 |
+
{
|
137 |
+
libxml_use_internal_errors(true);
|
138 |
+
|
139 |
+
if (is_string($source)) {
|
140 |
+
// check what's in the string (a package definition or a package filename)
|
141 |
+
if (0 === strpos($source, "<?xml")) {
|
142 |
+
// package definition xml
|
143 |
+
$this->_init($source);
|
144 |
+
} elseif (is_file($source) && is_readable($source)) {
|
145 |
+
// package archive filename
|
146 |
+
$this->_loadFile($source);
|
147 |
+
} else {
|
148 |
+
throw new Mage_Exception('Invalid package source');
|
149 |
+
}
|
150 |
+
} elseif (is_resource($source)) {
|
151 |
+
$this->_loadResource($source);
|
152 |
+
} elseif (is_null($source)) {
|
153 |
+
$this->_init();
|
154 |
+
} else {
|
155 |
+
throw new Mage_Exception('Invalid package source');
|
156 |
+
}
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Initializes an empty package object
|
161 |
+
*
|
162 |
+
* @param null|string $definition optional package definition xml
|
163 |
+
* @return Mage_Connect_Package
|
164 |
+
*/
|
165 |
+
protected function _init($definition=null)
|
166 |
+
{
|
167 |
+
|
168 |
+
if (!is_null($definition)) {
|
169 |
+
$this->_packageXml = simplexml_load_string($definition);
|
170 |
+
} else {
|
171 |
+
$packageXmlStub = <<<END
|
172 |
+
<?xml version="1.0"?>
|
173 |
+
<package>
|
174 |
+
<name />
|
175 |
+
<version />
|
176 |
+
<stability />
|
177 |
+
<license />
|
178 |
+
<channel />
|
179 |
+
<extends />
|
180 |
+
<summary />
|
181 |
+
<description />
|
182 |
+
<notes />
|
183 |
+
<authors />
|
184 |
+
<date />
|
185 |
+
<time />
|
186 |
+
<contents />
|
187 |
+
<compatible />
|
188 |
+
<dependencies />
|
189 |
+
</package>
|
190 |
+
END;
|
191 |
+
$this->_packageXml = simplexml_load_string($packageXmlStub);
|
192 |
+
}
|
193 |
+
return $this;
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Loads a package from specified file
|
198 |
+
*
|
199 |
+
* @param string $filename
|
200 |
+
* @return Mage_Connect_Package
|
201 |
+
*/
|
202 |
+
protected function _loadFile($filename='')
|
203 |
+
{
|
204 |
+
if (is_null($this->_reader)) {
|
205 |
+
$this->_reader = new Mage_Connect_Package_Reader($filename);
|
206 |
+
}
|
207 |
+
$content = $this->_reader->load();
|
208 |
+
$this->_packageXml = simplexml_load_string($content);
|
209 |
+
return $this;
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Creates a package and saves it
|
214 |
+
*
|
215 |
+
* @param string $path
|
216 |
+
* @return Mage_Connect_Package
|
217 |
+
*/
|
218 |
+
public function save($path)
|
219 |
+
{
|
220 |
+
$this->validate();
|
221 |
+
$path = rtrim($path, "\\/") . DS;
|
222 |
+
$this->_savePackage($path);
|
223 |
+
return $this;
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* Creates a package that is compatible with the previous version of Magento Connect Manager and saves it
|
228 |
+
*
|
229 |
+
* @param string $path
|
230 |
+
* @return Mage_Connect_Package
|
231 |
+
*/
|
232 |
+
public function saveV1x($path)
|
233 |
+
{
|
234 |
+
$this->validate();
|
235 |
+
$path = rtrim($path, "\\/") . DS;
|
236 |
+
$this->_savePackageV1x($path);
|
237 |
+
return $this;
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Creates a package archive and saves it to specified path
|
242 |
+
*
|
243 |
+
* @param string $path
|
244 |
+
* @return Mage_Connect_Package
|
245 |
+
*/
|
246 |
+
protected function _savePackage($path)
|
247 |
+
{
|
248 |
+
$fileName = $this->getReleaseFilename();
|
249 |
+
if (is_null($this->_writer)) {
|
250 |
+
$this->_writer = new Mage_Connect_Package_Writer($this->getContents(), $path.$fileName);
|
251 |
+
}
|
252 |
+
$this->_writer
|
253 |
+
->composePackage()
|
254 |
+
->addPackageXml($this->getPackageXml())
|
255 |
+
->archivePackage();
|
256 |
+
return $this;
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* Creates a package archive and saves it to specified path
|
261 |
+
* Package is compatible with the previous version of magento Connect Manager
|
262 |
+
*
|
263 |
+
* @param string $path
|
264 |
+
* @return Mage_Connect_Package
|
265 |
+
*/
|
266 |
+
protected function _savePackageV1x($path)
|
267 |
+
{
|
268 |
+
$fileName = $this->getReleaseFilename();
|
269 |
+
$writer = new Mage_Connect_Package_Writer($this->getContents(), $path.$fileName);
|
270 |
+
$writer->composePackageV1x($this->getContentsV1x())
|
271 |
+
->addPackageXml($this->_getPackageXmlV1x())
|
272 |
+
->archivePackage();
|
273 |
+
return $this;
|
274 |
+
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* Generate package xml that is compatible with first version of Magento Connect Manager
|
278 |
+
* Function uses already generated package xml to import data
|
279 |
+
*
|
280 |
+
* @return string
|
281 |
+
*/
|
282 |
+
protected function _getPackageXmlV1x()
|
283 |
+
{
|
284 |
+
$newPackageXml = $this->_packageXml;
|
285 |
+
$packageXmlV1xStub = <<<END
|
286 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
287 |
+
<package packagerversion="1.9.1"
|
288 |
+
version="2.0"
|
289 |
+
xmlns="http://pear.php.net/dtd/package-2.0"
|
290 |
+
xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
|
291 |
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
292 |
+
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" />
|
293 |
+
END;
|
294 |
+
$packageXmlV1x = simplexml_load_string($packageXmlV1xStub);
|
295 |
+
// Note: The previous version of MCM requires precise node order in package.xml file
|
296 |
+
$packageXmlV1x->addChild('name', (string)$newPackageXml->name);
|
297 |
+
$packageXmlV1x->addChild('channel', Mage::helper('connect')->convertChannelToV1x((string)$newPackageXml->channel));
|
298 |
+
$packageXmlV1x->addChild('summary', (string)$newPackageXml->summary);
|
299 |
+
$packageXmlV1x->addChild('description', (string)$newPackageXml->description);
|
300 |
+
// Import authors
|
301 |
+
foreach ($newPackageXml->authors->author as $author) {
|
302 |
+
$leadNode = $packageXmlV1x->addChild('lead');
|
303 |
+
$leadNode->addChild('name', (string)$author->name);
|
304 |
+
$leadNode->addChild('user', (string)$author->user);
|
305 |
+
$leadNode->addChild('email', (string)$author->email);
|
306 |
+
$leadNode->addChild('active', 'yes');
|
307 |
+
}
|
308 |
+
// Import date and time
|
309 |
+
$packageXmlV1x->addChild('date', (string)$newPackageXml->date);
|
310 |
+
$packageXmlV1x->addChild('time', (string)$newPackageXml->time);
|
311 |
+
// Import version
|
312 |
+
$versionNode = $packageXmlV1x->addChild('version');
|
313 |
+
$versionNode->addChild('release', (string)$newPackageXml->version);
|
314 |
+
$versionNode->addChild('api', (string)$newPackageXml->version);
|
315 |
+
// Import stability
|
316 |
+
$stabilityNode = $packageXmlV1x->addChild('stability');
|
317 |
+
$stabilityNode->addChild('release', (string)$newPackageXml->stability);
|
318 |
+
$stabilityNode->addChild('api', (string)$newPackageXml->stability);
|
319 |
+
// Import license
|
320 |
+
$licenseNode = $packageXmlV1x->addChild('license', (string)$newPackageXml->license);
|
321 |
+
if ($newPackageXml->license['uri']) {
|
322 |
+
$licenseNode->addAttribute('uri', (string)$newPackageXml->license['uri']);
|
323 |
+
}
|
324 |
+
$packageXmlV1x->addChild('notes', (string)$newPackageXml->notes);
|
325 |
+
// Import content
|
326 |
+
$conentsRootDirNode = $packageXmlV1x->addChild('contents')->addChild('dir');
|
327 |
+
$conentsRootDirNode->addAttribute('name', '/');
|
328 |
+
foreach ($newPackageXml->contents->target as $target) {
|
329 |
+
$role = (string)$target['name'];
|
330 |
+
$this->_mergeContentsToV1x($conentsRootDirNode, $target, $role);
|
331 |
+
}
|
332 |
+
// Import dependencies
|
333 |
+
$requiredDependenciesNode = $packageXmlV1x->addChild('dependencies')->addChild('required');
|
334 |
+
$requiredDependenciesPhpNode = $requiredDependenciesNode->addChild('php');
|
335 |
+
$requiredDependenciesPhpNode->addChild('min', (string)$newPackageXml->dependencies->required->php->min);
|
336 |
+
$requiredDependenciesPhpNode->addChild('max', (string)$newPackageXml->dependencies->required->php->max);
|
337 |
+
$requiredDependenciesNode->addChild('pearinstaller')->addChild('min','1.6.2');
|
338 |
+
// Handle packages
|
339 |
+
foreach ($newPackageXml->dependencies->required->package as $package) {
|
340 |
+
$packageNode = $requiredDependenciesNode->addChild('package');
|
341 |
+
$packageNode->addChild('name', (string)$package->name);
|
342 |
+
// Convert channel to previous version format
|
343 |
+
$channel = (string)$package->channel;
|
344 |
+
$channel = Mage::helper('connect')->convertChannelToV1x($channel);
|
345 |
+
$packageNode->addChild('channel', $channel);
|
346 |
+
$minVersion = (string)$package->min;
|
347 |
+
if ($minVersion) {
|
348 |
+
$packageNode->addChild('min', $minVersion);
|
349 |
+
}
|
350 |
+
$maxVersion = (string)$package->max;
|
351 |
+
if ($maxVersion) {
|
352 |
+
$packageNode->addChild('max', $maxVersion);
|
353 |
+
}
|
354 |
+
}
|
355 |
+
// Handle extensions
|
356 |
+
foreach ($newPackageXml->dependencies->required->extension as $extension) {
|
357 |
+
$extensionNode = $requiredDependenciesNode->addChild('extension');
|
358 |
+
$extensionNode->addChild('name', (string)$extension->name);
|
359 |
+
$minVersion = (string)$extension->min;
|
360 |
+
if ($minVersion) {
|
361 |
+
$extensionNode->addChild('min', $minVersion);
|
362 |
+
}
|
363 |
+
$maxVersion = (string)$extension->max;
|
364 |
+
if ($maxVersion) {
|
365 |
+
$extensionNode->addChild('max', $maxVersion);
|
366 |
+
}
|
367 |
+
}
|
368 |
+
$packageXmlV1x->addChild('phprelease');
|
369 |
+
|
370 |
+
return $packageXmlV1x->asXML();
|
371 |
+
}
|
372 |
+
|
373 |
+
/**
|
374 |
+
* Merge contents of source element into destination element
|
375 |
+
* Function converts <file/> and <dir/> nodes into format that is compatible
|
376 |
+
* with previous version of Magento Connect Manager
|
377 |
+
*
|
378 |
+
* @param SimpleXMLElement $destination
|
379 |
+
* @param SimpleXMLElement $source
|
380 |
+
* @param string $role
|
381 |
+
* @return Mage_Connect_Package
|
382 |
+
*/
|
383 |
+
protected function _mergeContentsToV1x($destination, $source, $role)
|
384 |
+
{
|
385 |
+
foreach ($source->children() as $child) {
|
386 |
+
if ($child->getName() == 'dir') {
|
387 |
+
$newDestination = $destination;
|
388 |
+
if ($child['name'] != '.') {
|
389 |
+
$directoryElement = $destination->addChild('dir');
|
390 |
+
$directoryElement->addAttribute('name', $child['name']);
|
391 |
+
$newDestination = $directoryElement;
|
392 |
+
}
|
393 |
+
$this->_mergeContentsToV1x($newDestination, $child, $role);
|
394 |
+
} elseif ($child->getName() == 'file') {
|
395 |
+
$fileElement = $destination->addChild('file');
|
396 |
+
$fileElement->addAttribute('name', $child['name']);
|
397 |
+
$fileElement->addAttribute('md5sum', $child['hash']);
|
398 |
+
$fileElement->addAttribute('role', $role);
|
399 |
+
}
|
400 |
+
}
|
401 |
+
return $this;
|
402 |
+
}
|
403 |
+
|
404 |
+
/**
|
405 |
+
* Retrieve Target object
|
406 |
+
*
|
407 |
+
* @return Mage_Connect_Package_Target
|
408 |
+
*/
|
409 |
+
protected function getTarget()
|
410 |
+
{
|
411 |
+
if (!$this->_target instanceof Mage_Connect_Package_Target) {
|
412 |
+
$this->_target = new Mage_Connect_Package_Target();
|
413 |
+
}
|
414 |
+
return $this->_target;
|
415 |
+
}
|
416 |
+
|
417 |
+
public function setTarget($arg)
|
418 |
+
{
|
419 |
+
if ($arg instanceof Mage_Connect_Package_Target) {
|
420 |
+
$this->_target = $arg;
|
421 |
+
}
|
422 |
+
}
|
423 |
+
|
424 |
+
/* Mutators */
|
425 |
+
|
426 |
+
/**
|
427 |
+
* Puts value to name
|
428 |
+
*
|
429 |
+
* @param string $name
|
430 |
+
* @return Mage_Connect_Package
|
431 |
+
*/
|
432 |
+
public function setName($name)
|
433 |
+
{
|
434 |
+
$this->_packageXml->name = $name;
|
435 |
+
return $this;
|
436 |
+
}
|
437 |
+
|
438 |
+
/**
|
439 |
+
* Puts value to <channel />
|
440 |
+
*
|
441 |
+
* @param string $channel
|
442 |
+
* @return Mage_Connect_Package
|
443 |
+
*/
|
444 |
+
public function setChannel($channel)
|
445 |
+
{
|
446 |
+
$this->_packageXml->channel = $channel;
|
447 |
+
return $this;
|
448 |
+
}
|
449 |
+
|
450 |
+
/**
|
451 |
+
* Puts value to <summary />
|
452 |
+
*
|
453 |
+
* @param string $summary
|
454 |
+
* @return Mage_Connect_Package
|
455 |
+
*/
|
456 |
+
public function setSummary($summary)
|
457 |
+
{
|
458 |
+
$this->_packageXml->summary = $summary;
|
459 |
+
return $this;
|
460 |
+
}
|
461 |
+
|
462 |
+
/**
|
463 |
+
* Puts value to <description />
|
464 |
+
*
|
465 |
+
* @param string $description
|
466 |
+
* @return Mage_Connect_Package
|
467 |
+
*/
|
468 |
+
public function setDescription($description)
|
469 |
+
{
|
470 |
+
$this->_packageXml->description = $description;
|
471 |
+
return $this;
|
472 |
+
}
|
473 |
+
|
474 |
+
/**
|
475 |
+
* Puts value to <authors />
|
476 |
+
*
|
477 |
+
* array(
|
478 |
+
* array('name'=>'Name1', 'user'=>'User1', 'email'=>'email1@email.com'),
|
479 |
+
* array('name'=>'Name2', 'user'=>'User2', 'email'=>'email2@email.com'),
|
480 |
+
* );
|
481 |
+
*
|
482 |
+
* @param array $authors
|
483 |
+
* @return Mage_Connect_Package
|
484 |
+
*/
|
485 |
+
public function setAuthors($authors)
|
486 |
+
{
|
487 |
+
$this->_authors = $authors;
|
488 |
+
foreach ($authors as $_author) {
|
489 |
+
$this->addAuthor($_author['name'], $_author['user'], $_author['email']);
|
490 |
+
}
|
491 |
+
return $this;
|
492 |
+
}
|
493 |
+
|
494 |
+
/**
|
495 |
+
* Add author to <authors/>
|
496 |
+
*
|
497 |
+
* @param string $name
|
498 |
+
* @param string $user
|
499 |
+
* @param string $email
|
500 |
+
* @return Mage_Connect_Package
|
501 |
+
*/
|
502 |
+
public function addAuthor($name=null, $user=null, $email=null)
|
503 |
+
{
|
504 |
+
$this->_authors[] = array(
|
505 |
+
'name' =>$name,
|
506 |
+
'user' =>$user,
|
507 |
+
'email'=>$email
|
508 |
+
);
|
509 |
+
$author = $this->_packageXml->authors->addChild('author');
|
510 |
+
$author->addChild('name', $name);
|
511 |
+
$author->addChild('user', $user);
|
512 |
+
$author->addChild('email', $email);
|
513 |
+
return $this;
|
514 |
+
}
|
515 |
+
|
516 |
+
/**
|
517 |
+
* Puts value to <date/>. Format should be Y-M-D.
|
518 |
+
*
|
519 |
+
* @param string $date
|
520 |
+
* @return Mage_Connect_Package
|
521 |
+
*/
|
522 |
+
public function setDate($date)
|
523 |
+
{
|
524 |
+
$this->_packageXml->date = $date;
|
525 |
+
return $this;
|
526 |
+
}
|
527 |
+
|
528 |
+
/**
|
529 |
+
* Puts value to <time />. Format should be H:i:s.
|
530 |
+
*
|
531 |
+
* @param string $time
|
532 |
+
* @return Mage_Connect_Package
|
533 |
+
*/
|
534 |
+
public function setTime($time)
|
535 |
+
{
|
536 |
+
$this->_packageXml->time = $time;
|
537 |
+
return $this;
|
538 |
+
}
|
539 |
+
|
540 |
+
/**
|
541 |
+
* Puts value to <version/>. Format should be X.Y.Z.
|
542 |
+
*
|
543 |
+
* @param string $version
|
544 |
+
* @return Mage_Connect_Package
|
545 |
+
*/
|
546 |
+
public function setVersion($version)
|
547 |
+
{
|
548 |
+
$this->_packageXml->version = $version;
|
549 |
+
return $this;
|
550 |
+
}
|
551 |
+
|
552 |
+
/**
|
553 |
+
* Puts value to <stability/>. It can be alpha, beta, devel and stable.
|
554 |
+
*
|
555 |
+
* @param string $stability
|
556 |
+
* @return Mage_Connect_Package
|
557 |
+
*/
|
558 |
+
public function setStability($stability)
|
559 |
+
{
|
560 |
+
$this->_packageXml->stability = $stability;
|
561 |
+
return $this;
|
562 |
+
}
|
563 |
+
|
564 |
+
/**
|
565 |
+
* Puts value to <license/>, also method can used for set attribute URI.
|
566 |
+
*
|
567 |
+
* @param string $license
|
568 |
+
* @param string $uri
|
569 |
+
* @return Mage_Connect_Package
|
570 |
+
*/
|
571 |
+
public function setLicense($license, $uri=null)
|
572 |
+
{
|
573 |
+
$this->_packageXml->license = $license;
|
574 |
+
if ($uri) {
|
575 |
+
$this->_packageXml->license['uri'] = $uri;
|
576 |
+
}
|
577 |
+
return $this;
|
578 |
+
}
|
579 |
+
|
580 |
+
/**
|
581 |
+
* Puts value to <notes/>.
|
582 |
+
*
|
583 |
+
* @param string $notes
|
584 |
+
* @return Mage_Connect_Package
|
585 |
+
*/
|
586 |
+
public function setNotes($notes)
|
587 |
+
{
|
588 |
+
$this->_packageXml->notes = $notes;
|
589 |
+
return $this;
|
590 |
+
}
|
591 |
+
|
592 |
+
/**
|
593 |
+
* Retrieve SimpleXMLElement node by xpath. If it absent, create new.
|
594 |
+
* For comparing nodes method uses attribute "name" in each nodes.
|
595 |
+
* If attribute "name" is same for both nodes, nodes are same.
|
596 |
+
*
|
597 |
+
* @param string $tag
|
598 |
+
* @param SimpleXMLElement $parent
|
599 |
+
* @param string $name
|
600 |
+
* @return SimpleXMLElement
|
601 |
+
*/
|
602 |
+
protected function _getNode($tag, $parent, $name='')
|
603 |
+
{
|
604 |
+
$found = false;
|
605 |
+
foreach ($parent->xpath($tag) as $_node) {
|
606 |
+
if ($_node['name'] == $name) {
|
607 |
+
$node = $_node;
|
608 |
+
$found = true;
|
609 |
+
break;
|
610 |
+
}
|
611 |
+
}
|
612 |
+
if (!$found) {
|
613 |
+
$node = $parent->addChild($tag);
|
614 |
+
if ($name) {
|
615 |
+
$node->addAttribute('name', $name);
|
616 |
+
}
|
617 |
+
}
|
618 |
+
return $node;
|
619 |
+
}
|
620 |
+
|
621 |
+
/**
|
622 |
+
* Add directory or file to <contents />.
|
623 |
+
*
|
624 |
+
* @param string $path Path to directory or file
|
625 |
+
* @param string $targetName Target name.
|
626 |
+
* @param string $hash MD5 hash of the file
|
627 |
+
* @return Mage_Connect_Package
|
628 |
+
*/
|
629 |
+
public function addContent($path, $targetName)
|
630 |
+
{
|
631 |
+
$found = false;
|
632 |
+
$parent = $this->_getNode('target', $this->_packageXml->contents, $targetName);
|
633 |
+
$source = str_replace('\\', '/', $path);
|
634 |
+
$directories = explode('/', dirname($source));
|
635 |
+
foreach ($directories as $directory) {
|
636 |
+
$parent = $this->_getNode('dir', $parent, $directory);
|
637 |
+
}
|
638 |
+
$fileName = basename($source);
|
639 |
+
if ($fileName!='') {
|
640 |
+
$fileNode = $parent->addChild('file');
|
641 |
+
$fileNode->addAttribute('name', $fileName);
|
642 |
+
$targetDir = $this->getTarget()->getTargetUri($targetName);
|
643 |
+
$hash = md5_file($targetDir.DS.$path);
|
644 |
+
$fileNode->addAttribute('hash', $hash);
|
645 |
+
}
|
646 |
+
return $this;
|
647 |
+
}
|
648 |
+
|
649 |
+
/**
|
650 |
+
* Add directory recursively (with subdirectory and file).
|
651 |
+
* Exclude and Include can be add using Regular Expression.
|
652 |
+
*
|
653 |
+
* @param string $targetName Target name
|
654 |
+
* @param string $targetDir Path for target name
|
655 |
+
* @param string $path Path to directory
|
656 |
+
* @param string $exclude Exclude
|
657 |
+
* @param string $include Include
|
658 |
+
* @return Mage_Connect_Package
|
659 |
+
*/
|
660 |
+
public function addContentDir($targetName, $path, $exclude=null, $include=null)
|
661 |
+
{
|
662 |
+
$targetDir = $this->getTarget()->getTargetUri($targetName);
|
663 |
+
$targetDirLen = strlen($targetDir . DS);
|
664 |
+
//get all subdirectories and files.
|
665 |
+
$entries = @glob($targetDir. DS . $path . DS . "{,.}*", GLOB_BRACE);
|
666 |
+
if (!empty($entries)) {
|
667 |
+
foreach ($entries as $entry) {
|
668 |
+
$filePath = substr($entry, $targetDirLen);
|
669 |
+
if (!empty($include) && !preg_match($include, $filePath)) {
|
670 |
+
continue;
|
671 |
+
}
|
672 |
+
if (!empty($exclude) && preg_match($exclude, $filePath)) {
|
673 |
+
continue;
|
674 |
+
}
|
675 |
+
if (is_dir($entry)) {
|
676 |
+
$baseName = basename($entry);
|
677 |
+
if (in_array($baseName, array('.', '..', '.svn'))) {
|
678 |
+
continue;
|
679 |
+
}
|
680 |
+
//for subdirectory call method recursively
|
681 |
+
$this->addContentDir($targetName, $filePath, $exclude, $include);
|
682 |
+
} elseif (is_file($entry)) {
|
683 |
+
$this->addContent($filePath, $targetName);
|
684 |
+
}
|
685 |
+
}
|
686 |
+
}
|
687 |
+
return $this;
|
688 |
+
}
|
689 |
+
|
690 |
+
/**
|
691 |
+
* Add value to <compatible />.
|
692 |
+
*
|
693 |
+
* @param string $packageName
|
694 |
+
* @param string $channel
|
695 |
+
* @param string $minVersion
|
696 |
+
* @param string $maxVersion
|
697 |
+
* @return Mage_Connect_Package
|
698 |
+
*/
|
699 |
+
public function addCompatible($packageName, $channel, $minVersion, $maxVersion)
|
700 |
+
{
|
701 |
+
$package = $this->_packageXml->compatible->addChild('package');
|
702 |
+
$package->addChild('name', $packageName);
|
703 |
+
$package->addChild('channel', $channel);
|
704 |
+
$package->addChild('min', $minVersion);
|
705 |
+
$package->addChild('max', $maxVersion);
|
706 |
+
return $this;
|
707 |
+
}
|
708 |
+
|
709 |
+
/**
|
710 |
+
* Set dependency from php version.
|
711 |
+
*
|
712 |
+
* @param string $minVersion
|
713 |
+
* @param string $maxVersion
|
714 |
+
* @return Mage_Connect_Package
|
715 |
+
*/
|
716 |
+
public function setDependencyPhpVersion($minVersion, $maxVersion)
|
717 |
+
{
|
718 |
+
$parent = $this->_packageXml->dependencies;
|
719 |
+
$parent = $this->_getNode('required', $parent);
|
720 |
+
$parent = $this->_getNode('php', $parent);
|
721 |
+
$parent->addChild('min', $minVersion);
|
722 |
+
$parent->addChild('max', $maxVersion);
|
723 |
+
return $this;
|
724 |
+
}
|
725 |
+
|
726 |
+
|
727 |
+
/**
|
728 |
+
* Check PHP version restriction
|
729 |
+
* @param $phpVersion PHP_VERSION by default
|
730 |
+
* @return true | string
|
731 |
+
*/
|
732 |
+
public function checkPhpVersion()
|
733 |
+
{
|
734 |
+
$min = $this->getDependencyPhpVersionMin();
|
735 |
+
$max = $this->getDependencyPhpVersionMax();
|
736 |
+
|
737 |
+
$minOk = $min? version_compare(PHP_VERSION, $min, ">=") : true;
|
738 |
+
$maxOk = $max? version_compare(PHP_VERSION, $max, "<=") : true;
|
739 |
+
|
740 |
+
if(!$minOk || !$maxOk) {
|
741 |
+
$err = "requires PHP version ";
|
742 |
+
if($min && $max) {
|
743 |
+
$err .= " >= $min and <= $max ";
|
744 |
+
} elseif($min) {
|
745 |
+
$err .= " >= $min ";
|
746 |
+
} elseif($max) {
|
747 |
+
$err .= " <= $max ";
|
748 |
+
}
|
749 |
+
$err .= " current is: ".PHP_VERSION;
|
750 |
+
return $err;
|
751 |
+
}
|
752 |
+
return true;
|
753 |
+
}
|
754 |
+
|
755 |
+
|
756 |
+
/**
|
757 |
+
* Check PHP extensions availability
|
758 |
+
* @throws Exceptiom on failure
|
759 |
+
* @return true | array
|
760 |
+
*/
|
761 |
+
public function checkPhpDependencies()
|
762 |
+
{
|
763 |
+
$errors = array();
|
764 |
+
foreach($this->getDependencyPhpExtensions() as $dep)
|
765 |
+
{
|
766 |
+
if(!extension_loaded($dep['name'])) {
|
767 |
+
$errors[] = $dep;
|
768 |
+
}
|
769 |
+
}
|
770 |
+
if(count($errors)) {
|
771 |
+
return $errors;
|
772 |
+
}
|
773 |
+
return true;
|
774 |
+
}
|
775 |
+
|
776 |
+
|
777 |
+
/**
|
778 |
+
* Set dependency from php extensions.
|
779 |
+
*
|
780 |
+
* $extension has next view:
|
781 |
+
* array('curl', 'mysql')
|
782 |
+
*
|
783 |
+
* @param array|string $extensions
|
784 |
+
* @return Mage_Connect_Package
|
785 |
+
*/
|
786 |
+
public function setDependencyPhpExtensions($extensions)
|
787 |
+
{
|
788 |
+
foreach($extensions as $_extension) {
|
789 |
+
$this->addDependencyExtension(
|
790 |
+
$_extension['name'],
|
791 |
+
$_extension['min_version'],
|
792 |
+
$_extension['max_version']
|
793 |
+
);
|
794 |
+
}
|
795 |
+
return $this;
|
796 |
+
}
|
797 |
+
|
798 |
+
/**
|
799 |
+
* Set dependency from another packages.
|
800 |
+
*
|
801 |
+
* $packages should contain:
|
802 |
+
* array(
|
803 |
+
* array('name'=>'test1', 'channel'=>'test1', 'min_version'=>'0.0.1', 'max_version'=>'0.1.0'),
|
804 |
+
* array('name'=>'test2', 'channel'=>'test2', 'min_version'=>'0.0.1', 'max_version'=>'0.1.0'),
|
805 |
+
* )
|
806 |
+
*
|
807 |
+
* @param array $packages
|
808 |
+
* @param bool $clear
|
809 |
+
* @return Mage_Connect_Package
|
810 |
+
*/
|
811 |
+
public function setDependencyPackages($packages, $clear = false)
|
812 |
+
{
|
813 |
+
if($clear) {
|
814 |
+
unset($this->_packageXml->dependencies->required->package);
|
815 |
+
}
|
816 |
+
|
817 |
+
foreach($packages as $_package) {
|
818 |
+
|
819 |
+
$filesArrayCondition = isset($_package['files']) && is_array($_package['files']);
|
820 |
+
$filesArray = $filesArrayCondition ? $_package['files'] : array();
|
821 |
+
|
822 |
+
$this->addDependencyPackage(
|
823 |
+
$_package['name'],
|
824 |
+
$_package['channel'],
|
825 |
+
$_package['min_version'],
|
826 |
+
$_package['max_version'],
|
827 |
+
$filesArray
|
828 |
+
);
|
829 |
+
}
|
830 |
+
return $this;
|
831 |
+
}
|
832 |
+
|
833 |
+
|
834 |
+
|
835 |
+
/**
|
836 |
+
* Add package to dependency packages.
|
837 |
+
*
|
838 |
+
* @param string $package
|
839 |
+
* @param string $channel
|
840 |
+
* @param string $minVersion
|
841 |
+
* @param string $maxVersion
|
842 |
+
* @return Mage_Connect_Package
|
843 |
+
*/
|
844 |
+
public function addDependencyPackage($name, $channel, $minVersion, $maxVersion, $files = array())
|
845 |
+
{
|
846 |
+
$parent = $this->_packageXml->dependencies;
|
847 |
+
$parent = $this->_getNode('required', $parent);
|
848 |
+
$parent = $parent->addChild('package');
|
849 |
+
$parent->addChild('name', $name);
|
850 |
+
$parent->addChild('channel', $channel);
|
851 |
+
$parent->addChild('min', $minVersion);
|
852 |
+
$parent->addChild('max', $maxVersion);
|
853 |
+
if(count($files)) {
|
854 |
+
$parent = $parent->addChild('files');
|
855 |
+
foreach($files as $row) {
|
856 |
+
if(!empty($row['target']) && !empty($row['path'])) {
|
857 |
+
$node = $parent->addChild("file");
|
858 |
+
$node["target"] = $row['target'];
|
859 |
+
$node["path"] = $row['path'];
|
860 |
+
|
861 |
+
}
|
862 |
+
}
|
863 |
+
}
|
864 |
+
return $this;
|
865 |
+
}
|
866 |
+
|
867 |
+
|
868 |
+
|
869 |
+
/**
|
870 |
+
* Add package to dependency extension.
|
871 |
+
*
|
872 |
+
* @param string $package
|
873 |
+
* @param string $minVersion
|
874 |
+
* @param string $maxVersion
|
875 |
+
* @return Mage_Connect_Package
|
876 |
+
*/
|
877 |
+
public function addDependencyExtension($name, $minVersion, $maxVersion)
|
878 |
+
{
|
879 |
+
$parent = $this->_packageXml->dependencies;
|
880 |
+
$parent = $this->_getNode('required', $parent);
|
881 |
+
$parent = $parent->addChild('extension');
|
882 |
+
$parent->addChild('name', $name);
|
883 |
+
$parent->addChild('min', $minVersion);
|
884 |
+
$parent->addChild('max', $maxVersion);
|
885 |
+
return $this;
|
886 |
+
}
|
887 |
+
|
888 |
+
/* Accessors */
|
889 |
+
|
890 |
+
/**
|
891 |
+
* Getter
|
892 |
+
*
|
893 |
+
* @return string
|
894 |
+
*/
|
895 |
+
public function getName()
|
896 |
+
{
|
897 |
+
return (string)$this->_packageXml->name;
|
898 |
+
}
|
899 |
+
|
900 |
+
/**
|
901 |
+
* Getter
|
902 |
+
*
|
903 |
+
* @return string
|
904 |
+
*/
|
905 |
+
public function getChannel()
|
906 |
+
{
|
907 |
+
return (string)$this->_packageXml->channel;
|
908 |
+
}
|
909 |
+
|
910 |
+
/**
|
911 |
+
* Getter
|
912 |
+
*
|
913 |
+
* @return string
|
914 |
+
*/
|
915 |
+
public function getSummary()
|
916 |
+
{
|
917 |
+
return (string)$this->_packageXml->summary;
|
918 |
+
}
|
919 |
+
|
920 |
+
/**
|
921 |
+
* Getter
|
922 |
+
*
|
923 |
+
* @return string
|
924 |
+
*/
|
925 |
+
public function getDescription()
|
926 |
+
{
|
927 |
+
return (string)$this->_packageXml->description;
|
928 |
+
}
|
929 |
+
|
930 |
+
/**
|
931 |
+
* Get list of authors in associative array.
|
932 |
+
*
|
933 |
+
* @return array
|
934 |
+
*/
|
935 |
+
public function getAuthors()
|
936 |
+
{
|
937 |
+
if (is_array($this->_authors)) return $this->_authors;
|
938 |
+
$this->_authors = array();
|
939 |
+
if(!isset($this->_packageXml->authors->author)) {
|
940 |
+
return array();
|
941 |
+
}
|
942 |
+
foreach ($this->_packageXml->authors->author as $_author) {
|
943 |
+
$this->_authors[] = array(
|
944 |
+
'name' => (string)$_author->name,
|
945 |
+
'user' => (string)$_author->user,
|
946 |
+
'email'=> (string)$_author->email
|
947 |
+
);
|
948 |
+
}
|
949 |
+
return $this->_authors;
|
950 |
+
}
|
951 |
+
|
952 |
+
/**
|
953 |
+
* Getter
|
954 |
+
*
|
955 |
+
* @return string
|
956 |
+
*/
|
957 |
+
public function getDate()
|
958 |
+
{
|
959 |
+
return (string)$this->_packageXml->date;
|
960 |
+
}
|
961 |
+
|
962 |
+
/**
|
963 |
+
* Getter
|
964 |
+
*
|
965 |
+
* @return string
|
966 |
+
*/
|
967 |
+
public function getTime()
|
968 |
+
{
|
969 |
+
return (string)$this->_packageXml->time;
|
970 |
+
}
|
971 |
+
|
972 |
+
/**
|
973 |
+
* Getter
|
974 |
+
*
|
975 |
+
* @return string
|
976 |
+
*/
|
977 |
+
public function getVersion()
|
978 |
+
{
|
979 |
+
return (string)$this->_packageXml->version;
|
980 |
+
}
|
981 |
+
|
982 |
+
/**
|
983 |
+
* Getter
|
984 |
+
*
|
985 |
+
* @return string
|
986 |
+
*/
|
987 |
+
public function getStability()
|
988 |
+
{
|
989 |
+
return (string)$this->_packageXml->stability;
|
990 |
+
}
|
991 |
+
|
992 |
+
/**
|
993 |
+
* Getter
|
994 |
+
*
|
995 |
+
* @return string
|
996 |
+
*/
|
997 |
+
public function getLicense()
|
998 |
+
{
|
999 |
+
return (string)$this->_packageXml->license;
|
1000 |
+
}
|
1001 |
+
|
1002 |
+
/**
|
1003 |
+
* Getter
|
1004 |
+
*
|
1005 |
+
* @return string
|
1006 |
+
*/
|
1007 |
+
public function getLicenseUri()
|
1008 |
+
{
|
1009 |
+
return (string)$this->_packageXml->license['uri'];
|
1010 |
+
}
|
1011 |
+
|
1012 |
+
/**
|
1013 |
+
* Getter
|
1014 |
+
*
|
1015 |
+
* @return string
|
1016 |
+
*/
|
1017 |
+
public function getNotes()
|
1018 |
+
{
|
1019 |
+
return (string)$this->_packageXml->notes;
|
1020 |
+
}
|
1021 |
+
|
1022 |
+
/**
|
1023 |
+
* Create list of all files from package.xml
|
1024 |
+
*
|
1025 |
+
* @return array
|
1026 |
+
*/
|
1027 |
+
public function getContents()
|
1028 |
+
{
|
1029 |
+
if (is_array($this->_contents)) return $this->_contents;
|
1030 |
+
$this->_contents = array();
|
1031 |
+
if(!isset($this->_packageXml->contents->target)) {
|
1032 |
+
return $this->_contents;
|
1033 |
+
}
|
1034 |
+
foreach($this->_packageXml->contents->target as $target) {
|
1035 |
+
$targetUri = $this->getTarget()->getTargetUri($target['name']);
|
1036 |
+
$this->_getList($target, $targetUri);
|
1037 |
+
}
|
1038 |
+
return $this->_contents;
|
1039 |
+
}
|
1040 |
+
|
1041 |
+
/**
|
1042 |
+
* Create list of all files from package.xml compatible with previous version of Magento Connect Manager
|
1043 |
+
*
|
1044 |
+
* @return array
|
1045 |
+
*/
|
1046 |
+
public function getContentsV1x()
|
1047 |
+
{
|
1048 |
+
$currentContents = $this->_contents;
|
1049 |
+
$this->_contents = array();
|
1050 |
+
|
1051 |
+
if(!isset($this->_packageXml->contents->target)) {
|
1052 |
+
return $this->_contents;
|
1053 |
+
}
|
1054 |
+
foreach($this->_packageXml->contents->target as $target) {
|
1055 |
+
$this->_getList($target, '');
|
1056 |
+
}
|
1057 |
+
$contents = $this->_contents;
|
1058 |
+
|
1059 |
+
$this->_contents = $currentContents;
|
1060 |
+
return $contents;
|
1061 |
+
}
|
1062 |
+
|
1063 |
+
/**
|
1064 |
+
* Helper for getContents(). Create recursively list.
|
1065 |
+
*
|
1066 |
+
* @param SimpleXMLElement $parent
|
1067 |
+
* @param string $path
|
1068 |
+
*/
|
1069 |
+
protected function _getList($parent, $path)
|
1070 |
+
{
|
1071 |
+
if (count($parent) == 0) {
|
1072 |
+
$this->_contents[] = $path;
|
1073 |
+
} else {
|
1074 |
+
foreach($parent as $_content) {
|
1075 |
+
$this->_getList($_content, ($path ? $path . DS : '') . $_content['name']);
|
1076 |
+
}
|
1077 |
+
}
|
1078 |
+
}
|
1079 |
+
|
1080 |
+
/**
|
1081 |
+
* Create list of all files from package.xml with hash
|
1082 |
+
*
|
1083 |
+
* @return array
|
1084 |
+
*/
|
1085 |
+
public function getHashContents()
|
1086 |
+
{
|
1087 |
+
if (is_array($this->_hashContents)) return $this->_hashContents;
|
1088 |
+
$this->_hashContents = array();
|
1089 |
+
if(!isset($this->_packageXml->contents->target)) {
|
1090 |
+
return $this->_hashContents;
|
1091 |
+
}
|
1092 |
+
foreach($this->_packageXml->contents->target as $target) {
|
1093 |
+
$targetUri = $this->getTarget()->getTargetUri($target['name']);
|
1094 |
+
$this->_getHashList($target, $targetUri);
|
1095 |
+
}
|
1096 |
+
return $this->_hashContents;
|
1097 |
+
}
|
1098 |
+
|
1099 |
+
/**
|
1100 |
+
* Helper for getHashContents(). Create recursively list.
|
1101 |
+
*
|
1102 |
+
* @param SimpleXMLElement $parent
|
1103 |
+
* @param string $path
|
1104 |
+
*/
|
1105 |
+
protected function _getHashList($parent, $path, $hash='')
|
1106 |
+
{
|
1107 |
+
if (count($parent) == 0) {
|
1108 |
+
$this->_hashContents[$path] = $hash;
|
1109 |
+
} else {
|
1110 |
+
foreach($parent as $_content) {
|
1111 |
+
$contentHash = '';
|
1112 |
+
if (isset($_content['hash'])) {
|
1113 |
+
$contentHash = (string)$_content['hash'];
|
1114 |
+
}
|
1115 |
+
$this->_getHashList($_content, ($path ? $path . DS : '') . $_content['name'], $contentHash);
|
1116 |
+
}
|
1117 |
+
}
|
1118 |
+
}
|
1119 |
+
|
1120 |
+
/**
|
1121 |
+
* Get compatible packages.
|
1122 |
+
*
|
1123 |
+
* @return array
|
1124 |
+
*/
|
1125 |
+
public function getCompatible()
|
1126 |
+
{
|
1127 |
+
if (is_array($this->_compatible)) return $this->_compatible;
|
1128 |
+
$this->_compatible = array();
|
1129 |
+
if(!isset($this->_packageXml->compatible->package)) {
|
1130 |
+
return array();
|
1131 |
+
}
|
1132 |
+
foreach ($this->_packageXml->compatible->package as $_package) {
|
1133 |
+
$this->_compatible[] = array(
|
1134 |
+
'name' => (string)$_package->name,
|
1135 |
+
'channel' => (string)$_package->channel,
|
1136 |
+
'min' => (string)$_package->min,
|
1137 |
+
'max' => (string)$_package->max
|
1138 |
+
);
|
1139 |
+
}
|
1140 |
+
return $this->_compatible;
|
1141 |
+
}
|
1142 |
+
|
1143 |
+
/**
|
1144 |
+
* Getter
|
1145 |
+
*
|
1146 |
+
* @return string
|
1147 |
+
*/
|
1148 |
+
public function getDependencyPhpVersionMin()
|
1149 |
+
{
|
1150 |
+
if(!isset($this->_packageXml->dependencies->required->php->min)) {
|
1151 |
+
return false;
|
1152 |
+
}
|
1153 |
+
return (string)$this->_packageXml->dependencies->required->php->min;
|
1154 |
+
}
|
1155 |
+
|
1156 |
+
/**
|
1157 |
+
* Getter
|
1158 |
+
*
|
1159 |
+
* @return string
|
1160 |
+
*/
|
1161 |
+
public function getDependencyPhpVersionMax()
|
1162 |
+
{
|
1163 |
+
if(!isset($this->_packageXml->dependencies->required->php->max)) {
|
1164 |
+
return false;
|
1165 |
+
}
|
1166 |
+
return (string)$this->_packageXml->dependencies->required->php->max;
|
1167 |
+
}
|
1168 |
+
|
1169 |
+
/**
|
1170 |
+
* Get list of php extensions.
|
1171 |
+
*
|
1172 |
+
* @return array
|
1173 |
+
*/
|
1174 |
+
public function getDependencyPhpExtensions()
|
1175 |
+
{
|
1176 |
+
if (is_array($this->_dependencyPhpExtensions)) return $this->_dependencyPhpExtensions;
|
1177 |
+
$this->_dependencyPhpExtensions = array();
|
1178 |
+
foreach($this->_packageXml->dependencies->required->extension as $_package) {
|
1179 |
+
$this->_dependencyPhpExtensions[] = array(
|
1180 |
+
'name' => (string)$_package->name,
|
1181 |
+
'min' => (string)$_package->min,
|
1182 |
+
'max' => (string)$_package->max,
|
1183 |
+
);
|
1184 |
+
}
|
1185 |
+
return $this->_dependencyPhpExtensions;
|
1186 |
+
}
|
1187 |
+
|
1188 |
+
/**
|
1189 |
+
* Get list of dependency packages.
|
1190 |
+
*
|
1191 |
+
* @return array
|
1192 |
+
*/
|
1193 |
+
public function getDependencyPackages()
|
1194 |
+
{
|
1195 |
+
$this->_dependencyPackages = array();
|
1196 |
+
foreach($this->_packageXml->dependencies->required->package as $_package) {
|
1197 |
+
$add = array(
|
1198 |
+
'name' => (string)$_package->name,
|
1199 |
+
'channel' => (string)$_package->channel,
|
1200 |
+
'min' => (string)$_package->min,
|
1201 |
+
'max' => (string)$_package->max,
|
1202 |
+
);
|
1203 |
+
if(isset($_package->files)) {
|
1204 |
+
$add['files'] = array();
|
1205 |
+
foreach($_package->files as $node) {
|
1206 |
+
if(isset($node->file)) {
|
1207 |
+
|
1208 |
+
$add['files'][] = array('target' => (string) $node->file['target'], 'path'=> (string) $node->file['path']);
|
1209 |
+
}
|
1210 |
+
}
|
1211 |
+
}
|
1212 |
+
$this->_dependencyPackages[] = $add;
|
1213 |
+
}
|
1214 |
+
return $this->_dependencyPackages;
|
1215 |
+
}
|
1216 |
+
|
1217 |
+
|
1218 |
+
|
1219 |
+
|
1220 |
+
/**
|
1221 |
+
* Get string with XML content.
|
1222 |
+
*
|
1223 |
+
* @return string
|
1224 |
+
*/
|
1225 |
+
public function getPackageXml()
|
1226 |
+
{
|
1227 |
+
return $this->_packageXml->asXml();
|
1228 |
+
}
|
1229 |
+
|
1230 |
+
|
1231 |
+
/**
|
1232 |
+
* Validator instance (single)
|
1233 |
+
*
|
1234 |
+
* @return Mage_Connect_Validator
|
1235 |
+
*/
|
1236 |
+
protected function validator()
|
1237 |
+
{
|
1238 |
+
if(is_null($this->_validator)) {
|
1239 |
+
$this->_validator = new Mage_Connect_Validator();
|
1240 |
+
}
|
1241 |
+
return $this->_validator;
|
1242 |
+
}
|
1243 |
+
|
1244 |
+
/**
|
1245 |
+
* Get validation error strings
|
1246 |
+
*
|
1247 |
+
* @return array
|
1248 |
+
*/
|
1249 |
+
public function getErrors()
|
1250 |
+
{
|
1251 |
+
return $this->_validationErrors;
|
1252 |
+
}
|
1253 |
+
|
1254 |
+
/**
|
1255 |
+
* Setter for validation errors
|
1256 |
+
*
|
1257 |
+
* @param array $errors
|
1258 |
+
* @return
|
1259 |
+
*/
|
1260 |
+
protected function setErrors(array $errors)
|
1261 |
+
{
|
1262 |
+
$this->_validationErrors = $errors;
|
1263 |
+
}
|
1264 |
+
|
1265 |
+
/**
|
1266 |
+
* Check validation result.
|
1267 |
+
* Returns true if package data is invalid.
|
1268 |
+
*
|
1269 |
+
* @return bool
|
1270 |
+
*/
|
1271 |
+
public function hasErrors()
|
1272 |
+
{
|
1273 |
+
return count($this->_validationErrors) != 0;
|
1274 |
+
}
|
1275 |
+
|
1276 |
+
/**
|
1277 |
+
* Validate package. Errors can be
|
1278 |
+
* retreived by calling getErrors();
|
1279 |
+
*
|
1280 |
+
* @return bool
|
1281 |
+
*/
|
1282 |
+
public function validate()
|
1283 |
+
{
|
1284 |
+
$v = $this->validator();
|
1285 |
+
|
1286 |
+
/**
|
1287 |
+
* Validation map
|
1288 |
+
*
|
1289 |
+
* Format:
|
1290 |
+
*
|
1291 |
+
* 'key' => array(
|
1292 |
+
* 'method' => this class method name to call, string, required
|
1293 |
+
* 'method_args' => optional args for 'method' call, array, optional
|
1294 |
+
* 'v_method' => validator method to call, string, required
|
1295 |
+
* 'error' => custom error string when validation fails, optional
|
1296 |
+
* if not set, error string fprmatted as "Invalid '$key' specified"
|
1297 |
+
* 'v_error_method' => validator method - when called returned error string
|
1298 |
+
* prepared by validator, optional,
|
1299 |
+
* if not set => see 'error'
|
1300 |
+
* 'optional' => optional value, if it's empty validation result ignored
|
1301 |
+
*
|
1302 |
+
*/
|
1303 |
+
$validateMap = array(
|
1304 |
+
'name' => array('method' => 'getName',
|
1305 |
+
'v_method' => 'validatePackageName',
|
1306 |
+
'error'=>"Invalid package name, allowed: [a-zA-Z0-9_-] chars"),
|
1307 |
+
'version' => array('method' => 'getVersion',
|
1308 |
+
'v_method' => 'validateVersion',
|
1309 |
+
'error'=>"Invalid version, should be like: x.x.x"),
|
1310 |
+
'stability' => array('method' => 'getStability',
|
1311 |
+
'v_method' => 'validateStability',
|
1312 |
+
'error'=>"Invalid stability"),
|
1313 |
+
'date' => array('method' => 'getDate',
|
1314 |
+
'v_method' => 'validateDate',
|
1315 |
+
'error'=>"Invalid date, should be YYYY-DD-MM"),
|
1316 |
+
'license_uri' => array('method' => 'getLicenseUri',
|
1317 |
+
'v_method' => 'validateLicenseUrl',
|
1318 |
+
'error'=>"Invalid license URL"),
|
1319 |
+
'channel' => array('method' => 'getChannel',
|
1320 |
+
'v_method' => 'validateChannelNameOrUri',
|
1321 |
+
'error'=>"Invalid channel URL"),
|
1322 |
+
'authors' => array('method' => 'getAuthors',
|
1323 |
+
'v_method' => 'validateAuthors',
|
1324 |
+
'v_error_method' => 'getErrors'),
|
1325 |
+
'php_min' => array('method' => 'getDependencyPhpVersionMin',
|
1326 |
+
'v_method' => 'validateVersion',
|
1327 |
+
'error' => 'PHP minimum version invalid',
|
1328 |
+
'optional' => true ),
|
1329 |
+
'php_max' => array('method' => 'getDependencyPhpVersionMax',
|
1330 |
+
'v_method' => 'validateVersion',
|
1331 |
+
'error' => 'PHP maximum version invalid',
|
1332 |
+
'optional' => true ),
|
1333 |
+
'compatible' => array('method' => 'getCompatible',
|
1334 |
+
'v_method' => 'validateCompatible',
|
1335 |
+
'v_error_method' => 'getErrors'),
|
1336 |
+
|
1337 |
+
|
1338 |
+
);
|
1339 |
+
|
1340 |
+
$errors = array();
|
1341 |
+
/**
|
1342 |
+
* Iterate validation map
|
1343 |
+
*/
|
1344 |
+
foreach($validateMap as $name=>$data) {
|
1345 |
+
|
1346 |
+
/**
|
1347 |
+
* Check mandatory rules fields
|
1348 |
+
*/
|
1349 |
+
if(!isset($data['method'], $data['v_method'])) {
|
1350 |
+
throw new Mage_Exception("Invalid rules specified!");
|
1351 |
+
}
|
1352 |
+
|
1353 |
+
$method = $data['method'];
|
1354 |
+
$validatorMethod = $data['v_method'];
|
1355 |
+
|
1356 |
+
/**
|
1357 |
+
* If $optional === false, value is mandatory
|
1358 |
+
*/
|
1359 |
+
$optional = isset($data['optional']) ? (bool) $data['optional'] : false;
|
1360 |
+
|
1361 |
+
/**
|
1362 |
+
* Check for method availability, package
|
1363 |
+
*/
|
1364 |
+
if(!method_exists($this, $method)) {
|
1365 |
+
throw new Mage_Exception("Invalid method specified for Package : $method");
|
1366 |
+
}
|
1367 |
+
|
1368 |
+
/**
|
1369 |
+
* Check for method availability, validator
|
1370 |
+
*/
|
1371 |
+
if(!method_exists($v, $validatorMethod)) {
|
1372 |
+
throw new Mage_Exception("Invalid method specified for Validator : $validatorMethod");
|
1373 |
+
}
|
1374 |
+
|
1375 |
+
/**
|
1376 |
+
* If $data['error'] => get error string from $data['error']
|
1377 |
+
* Else concatenate "Invalid '{$name}' specified"
|
1378 |
+
*/
|
1379 |
+
$errorString = isset($data['error']) ? $data['error'] : "Invalid '{$name}' specified";
|
1380 |
+
|
1381 |
+
/**
|
1382 |
+
* Additional method args check
|
1383 |
+
* array() by default
|
1384 |
+
*/
|
1385 |
+
$methodArgs = isset($data['method_args']) ? $data['method_args'] : array();
|
1386 |
+
|
1387 |
+
/**
|
1388 |
+
* Call package method
|
1389 |
+
*/
|
1390 |
+
$out = @call_user_func_array(array($this, $method), $methodArgs);
|
1391 |
+
|
1392 |
+
/**
|
1393 |
+
* Skip if result is empty and value is optional
|
1394 |
+
*/
|
1395 |
+
if(empty($out) && $optional) {
|
1396 |
+
continue;
|
1397 |
+
}
|
1398 |
+
|
1399 |
+
/**
|
1400 |
+
* Additional validator arguments, merged with array($out)
|
1401 |
+
*/
|
1402 |
+
$validatorArgs = isset($data['v_args']) ? array_merge(array($out), $data['v_args']) : array($out);
|
1403 |
+
|
1404 |
+
/**
|
1405 |
+
* Get validation result
|
1406 |
+
*/
|
1407 |
+
$result = call_user_func_array(array($v, $validatorMethod), $validatorArgs);
|
1408 |
+
|
1409 |
+
/**
|
1410 |
+
* Skip if validation success
|
1411 |
+
*/
|
1412 |
+
if($result) {
|
1413 |
+
continue;
|
1414 |
+
}
|
1415 |
+
|
1416 |
+
/**
|
1417 |
+
* From where to get error string?
|
1418 |
+
* If validator callback method specified, call it to get errors array
|
1419 |
+
* Else get it from $errorString - local error string
|
1420 |
+
*/
|
1421 |
+
$validatorFetchErrorsMethod = isset($data['v_error_method']) ? $data['v_error_method'] : false;
|
1422 |
+
if (false !== $validatorFetchErrorsMethod) {
|
1423 |
+
$errorString = call_user_func_array(array($v, $validatorFetchErrorsMethod), array());
|
1424 |
+
}
|
1425 |
+
|
1426 |
+
/**
|
1427 |
+
* If errors is array => merge
|
1428 |
+
* Else append
|
1429 |
+
*/
|
1430 |
+
if(is_array($errorString)) {
|
1431 |
+
$errors = array_merge($errors, $errorString);
|
1432 |
+
} else {
|
1433 |
+
$errors[] = $errorString;
|
1434 |
+
}
|
1435 |
+
}
|
1436 |
+
/**
|
1437 |
+
* Set local errors
|
1438 |
+
*/
|
1439 |
+
$this->setErrors($errors);
|
1440 |
+
/**
|
1441 |
+
* Return true if there's no errors :)
|
1442 |
+
*/
|
1443 |
+
return ! $this->hasErrors();
|
1444 |
+
}
|
1445 |
+
|
1446 |
+
/**
|
1447 |
+
* Return package release filename w/o extension
|
1448 |
+
* @return string
|
1449 |
+
*/
|
1450 |
+
public function getReleaseFilename()
|
1451 |
+
{
|
1452 |
+
return $this->getName()."-".$this->getVersion();
|
1453 |
+
}
|
1454 |
+
|
1455 |
+
/**
|
1456 |
+
* Return release filepath w/o extension
|
1457 |
+
* @return string
|
1458 |
+
*/
|
1459 |
+
public function getRelaseDirFilename()
|
1460 |
+
{
|
1461 |
+
return $this->getName() . DS . $this->getVersion() . DS . $this->getReleaseFilename();
|
1462 |
+
}
|
1463 |
+
|
1464 |
+
/**
|
1465 |
+
* Clear dependencies
|
1466 |
+
*
|
1467 |
+
* @return Mage_Connect_Package
|
1468 |
+
*/
|
1469 |
+
public function clearDependencies()
|
1470 |
+
{
|
1471 |
+
$this->_packageXml->dependencies = null;
|
1472 |
+
return $this;
|
1473 |
+
}
|
1474 |
+
|
1475 |
+
/**
|
1476 |
+
* Clear contents
|
1477 |
+
*
|
1478 |
+
* @return Mage_Connect_Package
|
1479 |
+
*/
|
1480 |
+
public function clearContents()
|
1481 |
+
{
|
1482 |
+
$this->_packageXml->contents = null;
|
1483 |
+
return $this;
|
1484 |
+
}
|
1485 |
+
|
1486 |
+
}
|
lib/Mage/Connect/Package/Extension.php
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
|
lib/Mage/Connect/Package/Hotfix.php
ADDED
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with Magento Connect Hotfix
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
|
35 |
+
class Mage_Connect_Package_Hotfix extends Mage_Connect_Package
|
36 |
+
{
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Initializes an empty package object
|
40 |
+
*
|
41 |
+
* @param null|string $definition optional package definition xml
|
42 |
+
* @return Mage_Connect_Package
|
43 |
+
*/
|
44 |
+
protected function _init($definition=null)
|
45 |
+
{
|
46 |
+
|
47 |
+
if (!is_null($definition)) {
|
48 |
+
$this->_packageXml = simplexml_load_string($definition);
|
49 |
+
} else {
|
50 |
+
$packageXmlStub = <<<END
|
51 |
+
<?xml version="1.0"?>
|
52 |
+
<package>
|
53 |
+
<name />
|
54 |
+
<version />
|
55 |
+
<stability />
|
56 |
+
<license />
|
57 |
+
<channel />
|
58 |
+
<extends />
|
59 |
+
<summary />
|
60 |
+
<description />
|
61 |
+
<notes />
|
62 |
+
<authors />
|
63 |
+
<date />
|
64 |
+
<time />
|
65 |
+
<replace />
|
66 |
+
<compatible />
|
67 |
+
<dependencies />
|
68 |
+
</package>
|
69 |
+
END;
|
70 |
+
$this->_packageXml = simplexml_load_string($packageXmlStub);
|
71 |
+
}
|
72 |
+
return $this;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Add content to node <replace/>
|
77 |
+
*
|
78 |
+
* @return Mage_Connect_Package_Hotfix
|
79 |
+
*/
|
80 |
+
public function addReplace($path, $targetName)
|
81 |
+
{
|
82 |
+
$found = false;
|
83 |
+
$parent = $this->_getNode('target', $this->_packageXml->replace, $targetName);
|
84 |
+
$path = str_replace('\\', '/', $path);
|
85 |
+
$directories = explode('/', dirname($path));
|
86 |
+
foreach ($directories as $directory) {
|
87 |
+
$parent = $this->_getNode('dir', $parent, $directory);
|
88 |
+
}
|
89 |
+
$fileName = basename($path);
|
90 |
+
if ($fileName!='') {
|
91 |
+
$fileNode = $parent->addChild('file');
|
92 |
+
$fileNode->addAttribute('name', $fileName);
|
93 |
+
}
|
94 |
+
return $this;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Add directory recursively (with subdirectory and file).
|
99 |
+
* Exclude and Include can be add using Regular Expression.
|
100 |
+
*
|
101 |
+
* @param string $targetName Target name
|
102 |
+
* @param string $targetDir Path for target name
|
103 |
+
* @param string $path Path to directory
|
104 |
+
* @param string $exclude Exclude
|
105 |
+
* @param string $include Include
|
106 |
+
* @return Mage_Connect_Package
|
107 |
+
*/
|
108 |
+
public function addReplaceDir($targetName, $targetDir, $path, $exclude=null, $include=null)
|
109 |
+
{
|
110 |
+
$targetDirLen = strlen($targetDir);
|
111 |
+
//get all subdirectories and files.
|
112 |
+
$entries = @glob($targetDir.$path.DS."*");
|
113 |
+
if (!empty($entries)) {
|
114 |
+
foreach ($entries as $entry) {
|
115 |
+
$filePath = substr($entry, $targetDirLen);
|
116 |
+
if (!empty($include) && !preg_match($include, $filePath)) {
|
117 |
+
continue;
|
118 |
+
}
|
119 |
+
if (!empty($ignore) && preg_match($exclude, $filePath)) {
|
120 |
+
continue;
|
121 |
+
}
|
122 |
+
if (is_dir($entry)) {
|
123 |
+
$baseName = basename($entry);
|
124 |
+
if ('.'===$baseName || '..'===$baseName) {
|
125 |
+
continue;
|
126 |
+
}
|
127 |
+
//for subdirectory call method recursively
|
128 |
+
$this->addReplaceDir($targetName, $targetDir, $filePath, $exclude, $include);
|
129 |
+
} elseif (is_file($entry)) {
|
130 |
+
$this->addReplace($filePath, $targetName);
|
131 |
+
}
|
132 |
+
}
|
133 |
+
}
|
134 |
+
return $this;
|
135 |
+
}
|
136 |
+
|
137 |
+
}
|
lib/Mage/Connect/Package/Maintainer.php
ADDED
File without changes
|
lib/Mage/Connect/Package/Reader.php
ADDED
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to get package.xml from different places.
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Connect_Package_Reader
|
35 |
+
{
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Name of package file
|
39 |
+
*/
|
40 |
+
const DEFAULT_NAME_PACKAGE = 'package.xml';
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Temporary dir for extract DEFAULT_NAME_PACKAGE.
|
44 |
+
*/
|
45 |
+
const PATH_TO_TEMPORARY_DIRECTORY = 'var/package/tmp/';
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Current path to file.
|
49 |
+
*
|
50 |
+
* @var string
|
51 |
+
*/
|
52 |
+
protected $_file = '';
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Archivator is used for extract DEFAULT_NAME_PACKAGE.
|
56 |
+
*
|
57 |
+
* @var Mage_Archive
|
58 |
+
*/
|
59 |
+
protected $_archivator = null;
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Constructor initializes $_file.
|
63 |
+
*
|
64 |
+
* @param string $file
|
65 |
+
* @return Mage_Connect_Package_Reader
|
66 |
+
*/
|
67 |
+
public function __construct($file='')
|
68 |
+
{
|
69 |
+
if ($file) {
|
70 |
+
$this->_file = $file;
|
71 |
+
} else {
|
72 |
+
$this->_file = self::DEFAULT_NAME_PACKAGE;
|
73 |
+
}
|
74 |
+
return $this;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Retrieve archivator.
|
79 |
+
*
|
80 |
+
* @return Mage_Archive
|
81 |
+
*/
|
82 |
+
protected function _getArchivator()
|
83 |
+
{
|
84 |
+
if (is_null($this->_archivator)) {
|
85 |
+
$this->_archivator = new Mage_Archive();
|
86 |
+
}
|
87 |
+
return $this->_archivator;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Open file directly or from archive and return his content.
|
92 |
+
*
|
93 |
+
* @return string Content of file $file
|
94 |
+
*/
|
95 |
+
public function load()
|
96 |
+
{
|
97 |
+
if (!is_file($this->_file) || !is_readable($this->_file)) {
|
98 |
+
throw new Exception('Invalid package file specified.');
|
99 |
+
}
|
100 |
+
if ($this->_getArchivator()->isArchive($this->_file)) {
|
101 |
+
@mkdir(self::PATH_TO_TEMPORARY_DIRECTORY, 0777, true);
|
102 |
+
$this->_file = $this->_getArchivator()->extract(
|
103 |
+
self::DEFAULT_NAME_PACKAGE,
|
104 |
+
$this->_file,
|
105 |
+
self::PATH_TO_TEMPORARY_DIRECTORY
|
106 |
+
);
|
107 |
+
}
|
108 |
+
$xmlContent = $this->_readFile();
|
109 |
+
return $xmlContent;
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Read content file.
|
114 |
+
*
|
115 |
+
* @return string Content of file $file
|
116 |
+
*/
|
117 |
+
protected function _readFile()
|
118 |
+
{
|
119 |
+
$handle = fopen($this->_file, 'r');
|
120 |
+
try {
|
121 |
+
$data = $this->_loadResource($handle);
|
122 |
+
} catch (Mage_Exception $e) {
|
123 |
+
fclose($handle);
|
124 |
+
throw $e;
|
125 |
+
}
|
126 |
+
fclose($handle);
|
127 |
+
return $data;
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Loads a package from specified resource
|
132 |
+
*
|
133 |
+
* @param resource $resource only file resources are supported at the moment
|
134 |
+
* @return Mage_Connect_Package
|
135 |
+
*/
|
136 |
+
protected function _loadResource(&$resource)
|
137 |
+
{
|
138 |
+
$data = '';
|
139 |
+
//var_dump("====", $res, get_resource_type($resource));
|
140 |
+
if ('stream' === get_resource_type($resource)) {
|
141 |
+
while (!feof($resource)) {
|
142 |
+
$data .= fread($resource, 10240);
|
143 |
+
}
|
144 |
+
} else {
|
145 |
+
throw new Mage_Exception('Unsupported resource type');
|
146 |
+
}
|
147 |
+
return $data;
|
148 |
+
}
|
149 |
+
|
150 |
+
}
|
lib/Mage/Connect/Package/Target.php
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to get targets and their basepath from target.xml.
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
|
35 |
+
class Mage_Connect_Package_Target
|
36 |
+
{
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Object contains all contents from target.xml.
|
40 |
+
*
|
41 |
+
* @var array
|
42 |
+
*/
|
43 |
+
protected $_targetMap=null;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Cache for targets.
|
47 |
+
*
|
48 |
+
* @var array
|
49 |
+
*/
|
50 |
+
protected $_targets;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Retrieve content from target.xml.
|
54 |
+
*
|
55 |
+
* @return SimpleXMLElement
|
56 |
+
*/
|
57 |
+
protected function _getTargetMap()
|
58 |
+
{
|
59 |
+
if (is_null($this->_targetMap)) {
|
60 |
+
$this->_targetMap = array();
|
61 |
+
$this->_targetMap[] = array('name'=>"magelocal" ,'label'=>"Magento Local module file" , 'uri'=>"./app/code/local");
|
62 |
+
$this->_targetMap[] = array('name'=>"magecommunity" ,'label'=>"Magento Community module file" , 'uri'=>"./app/code/community");
|
63 |
+
$this->_targetMap[] = array('name'=>"magecore" ,'label'=>"Magento Core team module file" , 'uri'=>"./app/code/core");
|
64 |
+
$this->_targetMap[] = array('name'=>"magedesign" ,'label'=>"Magento User Interface (layouts, templates)" , 'uri'=>"./app/design");
|
65 |
+
$this->_targetMap[] = array('name'=>"mageetc" ,'label'=>"Magento Global Configuration" , 'uri'=>"./app/etc");
|
66 |
+
$this->_targetMap[] = array('name'=>"magelib" ,'label'=>"Magento PHP Library file" , 'uri'=>"./lib");
|
67 |
+
$this->_targetMap[] = array('name'=>"magelocale" ,'label'=>"Magento Locale language file" , 'uri'=>"./app/locale");
|
68 |
+
$this->_targetMap[] = array('name'=>"magemedia" ,'label'=>"Magento Media library" , 'uri'=>"./media");
|
69 |
+
$this->_targetMap[] = array('name'=>"mageskin" ,'label'=>"Magento Theme Skin (Images, CSS, JS)" , 'uri'=>"./skin");
|
70 |
+
$this->_targetMap[] = array('name'=>"mageweb" ,'label'=>"Magento Other web accessible file" , 'uri'=>".");
|
71 |
+
$this->_targetMap[] = array('name'=>"magetest" ,'label'=>"Magento PHPUnit test" , 'uri'=>"./tests");
|
72 |
+
$this->_targetMap[] = array('name'=>"mage" ,'label'=>"Magento other" , 'uri'=>".");
|
73 |
+
}
|
74 |
+
return $this->_targetMap;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Retrieve targets as associative array from target.xml.
|
79 |
+
*
|
80 |
+
* @return array
|
81 |
+
*/
|
82 |
+
public function getTargets()
|
83 |
+
{
|
84 |
+
if (!is_array($this->_targets)) {
|
85 |
+
$this->_targets = array();
|
86 |
+
if($this->_getTargetMap()) {
|
87 |
+
foreach ($this->_getTargetMap() as $_target) {
|
88 |
+
$this->_targets[$_target['name']] = (string)$_target['uri'];
|
89 |
+
}
|
90 |
+
}
|
91 |
+
}
|
92 |
+
return $this->_targets;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Retrieve tragets with label for select options.
|
97 |
+
*
|
98 |
+
* @return array
|
99 |
+
*/
|
100 |
+
public function getLabelTargets()
|
101 |
+
{
|
102 |
+
$targets = array();
|
103 |
+
foreach ($this->_getTargetMap() as $_target) {
|
104 |
+
$targets[$_target['name']] = $_target['label'];
|
105 |
+
}
|
106 |
+
return $targets;
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Get uri by target's name.
|
111 |
+
*
|
112 |
+
* @param string $name
|
113 |
+
* @return string
|
114 |
+
*/
|
115 |
+
public function getTargetUri($name)
|
116 |
+
{
|
117 |
+
foreach ($this->getTargets() as $_name=>$_uri) {
|
118 |
+
if ($name == $_name) {
|
119 |
+
return $_uri;
|
120 |
+
}
|
121 |
+
}
|
122 |
+
return '';
|
123 |
+
}
|
124 |
+
|
125 |
+
|
126 |
+
}
|
lib/Mage/Connect/Package/VO.php
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
class Mage_Connect_Package_VO implements Iterator
|
28 |
+
{
|
29 |
+
protected $properties = array(
|
30 |
+
'name' => '',
|
31 |
+
'package_type_vesrion' => '',
|
32 |
+
'cahnnel' => '',
|
33 |
+
'extends' => '',
|
34 |
+
'summary' => '',
|
35 |
+
'description' => '',
|
36 |
+
'authors' => '',
|
37 |
+
'date' => '',
|
38 |
+
'time' => '',
|
39 |
+
'version' => '',
|
40 |
+
'stability' => 'dev',
|
41 |
+
'license' => '',
|
42 |
+
'license_uri' => '',
|
43 |
+
'contents' => '',
|
44 |
+
'compatible' => '',
|
45 |
+
'hotfix' => ''
|
46 |
+
);
|
47 |
+
|
48 |
+
public function rewind() {
|
49 |
+
reset($this->properties);
|
50 |
+
}
|
51 |
+
|
52 |
+
public function valid() {
|
53 |
+
return current($this->properties) !== false;
|
54 |
+
}
|
55 |
+
|
56 |
+
public function key() {
|
57 |
+
return key($this->properties);
|
58 |
+
}
|
59 |
+
|
60 |
+
public function current() {
|
61 |
+
return current($this->properties);
|
62 |
+
}
|
63 |
+
|
64 |
+
public function next() {
|
65 |
+
next($this->properties);
|
66 |
+
}
|
67 |
+
|
68 |
+
public function __get($var)
|
69 |
+
{
|
70 |
+
if (isset($this->properties[$var])) {
|
71 |
+
return $this->properties[$var];
|
72 |
+
}
|
73 |
+
return null;
|
74 |
+
}
|
75 |
+
|
76 |
+
public function __set($var, $value)
|
77 |
+
{
|
78 |
+
if (is_string($value)) {
|
79 |
+
$value = trim($value);
|
80 |
+
}
|
81 |
+
if (isset($this->properties[$var])) {
|
82 |
+
if ($value === null) {
|
83 |
+
$value = '';
|
84 |
+
}
|
85 |
+
$this->properties[$var] = $value;
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
public function toArray()
|
90 |
+
{
|
91 |
+
return $this->properties;
|
92 |
+
}
|
93 |
+
|
94 |
+
}
|
95 |
+
|
96 |
+
|
lib/Mage/Connect/Package/Writer.php
ADDED
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to create archive.
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Connect_Package_Writer
|
35 |
+
{
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Name of package configuration file
|
39 |
+
*/
|
40 |
+
const DEFAULT_NAME_PACKAGE_CONFIG = 'package.xml';
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Temporary dir for extract DEFAULT_NAME_PACKAGE.
|
44 |
+
*/
|
45 |
+
const PATH_TO_TEMPORARY_DIRECTORY = 'var/package/tmp/';
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Files are used in package.
|
49 |
+
*
|
50 |
+
* @var array
|
51 |
+
*/
|
52 |
+
protected $_files = array();
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Archivator is used for extract DEFAULT_NAME_PACKAGE.
|
56 |
+
*
|
57 |
+
* @var Mage_Archive
|
58 |
+
*/
|
59 |
+
protected $_archivator = null;
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Name of package with extension. Extension should be only one.
|
63 |
+
* "package.tar.gz" is not ability, only "package.tgz".
|
64 |
+
*
|
65 |
+
* @var string
|
66 |
+
*/
|
67 |
+
protected $_namePackage = 'package';
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Temporary directory where package is situated.
|
71 |
+
*
|
72 |
+
* @var string
|
73 |
+
*/
|
74 |
+
protected $_temporaryPackageDir = '';
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Path to archive with package.
|
78 |
+
*
|
79 |
+
* @var mixed
|
80 |
+
*/
|
81 |
+
protected $_pathToArchive = '';
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Constructor initializes $_file.
|
85 |
+
*
|
86 |
+
* @param array $files
|
87 |
+
* @param string $namePackage
|
88 |
+
* @return Mage_Connect_Package_Reader
|
89 |
+
*/
|
90 |
+
public function __construct($files, $namePackage='')
|
91 |
+
{
|
92 |
+
$this->_files = $files;
|
93 |
+
$this->_namePackage = $namePackage;
|
94 |
+
return $this;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Retrieve archivator.
|
99 |
+
*
|
100 |
+
* @return Mage_Archive
|
101 |
+
*/
|
102 |
+
protected function _getArchivator()
|
103 |
+
{
|
104 |
+
if (is_null($this->_archivator)) {
|
105 |
+
$this->_archivator = new Mage_Archive();
|
106 |
+
}
|
107 |
+
return $this->_archivator;
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Create dir in PATH_TO_TEMPORARY_DIRECTORY and move all files
|
112 |
+
* to this dir.
|
113 |
+
*
|
114 |
+
* @return Mage_Connect_Package_Writer
|
115 |
+
*/
|
116 |
+
public function composePackage()
|
117 |
+
{
|
118 |
+
@mkdir(self::PATH_TO_TEMPORARY_DIRECTORY, 0777, true);
|
119 |
+
$root = self::PATH_TO_TEMPORARY_DIRECTORY . basename($this->_namePackage);
|
120 |
+
@mkdir($root, 0777, true);
|
121 |
+
foreach ($this->_files as $file) {
|
122 |
+
|
123 |
+
if (is_dir($file) || is_file($file)) {
|
124 |
+
$fileName = basename($file);
|
125 |
+
$filePath = dirname($file);
|
126 |
+
@mkdir($root . DS . $filePath, 0777, true);
|
127 |
+
if (is_file($file)) {
|
128 |
+
copy($file, $root . DS . $filePath . DS . $fileName);
|
129 |
+
} else {
|
130 |
+
@mkdir($root . DS . $filePath . $fileName, 0777);
|
131 |
+
}
|
132 |
+
}
|
133 |
+
}
|
134 |
+
$this->_temporaryPackageDir = $root;
|
135 |
+
return $this;
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Create dir in PATH_TO_TEMPORARY_DIRECTORY and move all files
|
140 |
+
* to this dir.
|
141 |
+
* This dir has a structure compatible with previous version of Magento Connact Manager
|
142 |
+
*
|
143 |
+
* @param arra $destinationFiles
|
144 |
+
* @return Mage_Connect_Package_Writer
|
145 |
+
*/
|
146 |
+
public function composePackageV1x(array $destinationFiles)
|
147 |
+
{
|
148 |
+
@mkdir(self::PATH_TO_TEMPORARY_DIRECTORY, 0777, true);
|
149 |
+
$root = self::PATH_TO_TEMPORARY_DIRECTORY . basename($this->_namePackage);
|
150 |
+
@mkdir($root, 0777, true);
|
151 |
+
$packageFilesDir = $root . DS . basename($this->_namePackage);
|
152 |
+
@mkdir($packageFilesDir, 0777, true);
|
153 |
+
foreach ($this->_files as $index => $file) {
|
154 |
+
$destinationFile = $destinationFiles[$index];
|
155 |
+
if (is_dir($file) || is_file($file)) {
|
156 |
+
$fileName = basename($destinationFile);
|
157 |
+
$filePath = dirname($destinationFile);
|
158 |
+
@mkdir($packageFilesDir . DS . $filePath, 0777, true);
|
159 |
+
if (is_file($file)) {
|
160 |
+
copy($file, $packageFilesDir . DS . $filePath . DS . $fileName);
|
161 |
+
} else {
|
162 |
+
@mkdir($packageFilesDir . DS . $filePath . $fileName, 0777);
|
163 |
+
}
|
164 |
+
}
|
165 |
+
}
|
166 |
+
$this->_temporaryPackageDir = $root;
|
167 |
+
return $this;
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Add package.xml to temporary package directory.
|
172 |
+
*
|
173 |
+
* @param $content
|
174 |
+
* @return Mage_Connect_Package_Writer
|
175 |
+
*/
|
176 |
+
public function addPackageXml($content)
|
177 |
+
{
|
178 |
+
file_put_contents($this->_temporaryPackageDir . DS . self::DEFAULT_NAME_PACKAGE_CONFIG, $content);
|
179 |
+
return $this;
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Archives package.
|
184 |
+
*
|
185 |
+
* @return Mage_Connect_Package_Writer
|
186 |
+
*/
|
187 |
+
public function archivePackage()
|
188 |
+
{
|
189 |
+
$this->_pathToArchive = $this->_getArchivator()->pack(
|
190 |
+
$this->_temporaryPackageDir,
|
191 |
+
$this->_namePackage.'.tgz',
|
192 |
+
true);
|
193 |
+
|
194 |
+
//delete temporary dir
|
195 |
+
Mage_System_Dirs::rm(array("-r", $this->_temporaryPackageDir));
|
196 |
+
return $this;
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Getter for pathToArchive
|
201 |
+
*
|
202 |
+
* @return string
|
203 |
+
*/
|
204 |
+
public function getPathToArchive()
|
205 |
+
{
|
206 |
+
return $this->_pathToArchive;
|
207 |
+
}
|
208 |
+
|
209 |
+
}
|
lib/Mage/Connect/Packager.php
ADDED
@@ -0,0 +1,662 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to manipulate with packages
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
|
35 |
+
class Mage_Connect_Packager
|
36 |
+
{
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Constructor
|
40 |
+
* @param Mage_connect_Config $config
|
41 |
+
*/
|
42 |
+
public function __construct()
|
43 |
+
{
|
44 |
+
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
*
|
49 |
+
* @var Mage_Archive
|
50 |
+
*/
|
51 |
+
protected $_archiver = null;
|
52 |
+
protected $_http = null;
|
53 |
+
|
54 |
+
|
55 |
+
|
56 |
+
/**
|
57 |
+
*
|
58 |
+
* @return Mage_Archive
|
59 |
+
*/
|
60 |
+
public function getArchiver()
|
61 |
+
{
|
62 |
+
if(is_null($this->_archiver)) {
|
63 |
+
$this->_archiver = new Mage_Archive();
|
64 |
+
}
|
65 |
+
return $this->_archiver;
|
66 |
+
}
|
67 |
+
|
68 |
+
public function getDownloader()
|
69 |
+
{
|
70 |
+
if(is_null($this->_http)) {
|
71 |
+
$this->_http = Mage_HTTP_Client::getInstance();
|
72 |
+
}
|
73 |
+
return $this->_http;
|
74 |
+
}
|
75 |
+
|
76 |
+
|
77 |
+
public function getRemoteConf($ftpString)
|
78 |
+
{
|
79 |
+
$ftpObj = new Mage_Connect_Ftp();
|
80 |
+
$ftpObj->connect($ftpString);
|
81 |
+
$cfgFile = "connect.cfg";
|
82 |
+
$cacheFile = "cache.cfg";
|
83 |
+
|
84 |
+
|
85 |
+
$wd = $ftpObj->getcwd();
|
86 |
+
|
87 |
+
$remoteConfigExists = $ftpObj->fileExists($cfgFile);
|
88 |
+
$tempConfigFile = uniqid($cfgFile."_temp");
|
89 |
+
if(!$remoteConfigExists) {
|
90 |
+
$remoteCfg = new Mage_Connect_Config($tempConfigFile);
|
91 |
+
$remoteCfg->store();
|
92 |
+
$ftpObj->upload($cfgFile, $tempConfigFile);
|
93 |
+
} else {
|
94 |
+
$ftpObj->get($tempConfigFile, $cfgFile);
|
95 |
+
$remoteCfg = new Mage_Connect_Config($tempConfigFile);
|
96 |
+
}
|
97 |
+
|
98 |
+
$ftpObj->chdir($wd);
|
99 |
+
|
100 |
+
$remoteCacheExists = $ftpObj->fileExists($cacheFile);
|
101 |
+
$tempCacheFile = uniqid($cacheFile."_temp");
|
102 |
+
|
103 |
+
if(!$remoteCacheExists) {
|
104 |
+
$remoteCache = new Mage_Connect_Singleconfig($tempCacheFile);
|
105 |
+
$remoteCache->clear();
|
106 |
+
$ftpObj->upload($cacheFile, $tempCacheFile);
|
107 |
+
} else {
|
108 |
+
$ftpObj->get($tempCacheFile, $cacheFile);
|
109 |
+
$remoteCache = new Mage_Connect_Singleconfig($tempCacheFile);
|
110 |
+
}
|
111 |
+
$ftpObj->chdir($wd);
|
112 |
+
return array($remoteCache, $remoteCfg, $ftpObj);
|
113 |
+
}
|
114 |
+
|
115 |
+
|
116 |
+
public function getRemoteCache($ftpString)
|
117 |
+
{
|
118 |
+
|
119 |
+
$ftpObj = new Mage_Connect_Ftp();
|
120 |
+
$ftpObj->connect($ftpString);
|
121 |
+
$remoteConfigExists = $ftpObj->fileExists("cache.cfg");
|
122 |
+
if(!$remoteConfigExists) {
|
123 |
+
$configFile= uniqid("temp_cachecfg_");
|
124 |
+
$remoteCfg = new Mage_Connect_Singleconfig($configFile);
|
125 |
+
$remoteCfg->clear();
|
126 |
+
$ftpObj->upload("cache.cfg", $configFile);
|
127 |
+
} else {
|
128 |
+
$configFile = uniqid("temp_cachecfg_");
|
129 |
+
$ftpObj->get($configFile, "cache.cfg");
|
130 |
+
$remoteCfg = new Mage_Connect_Singleconfig($configFile);
|
131 |
+
}
|
132 |
+
return array($remoteCfg, $ftpObj);
|
133 |
+
}
|
134 |
+
|
135 |
+
|
136 |
+
public function getRemoteConfig($ftpString)
|
137 |
+
{
|
138 |
+
$ftpObj = new Mage_Connect_Ftp();
|
139 |
+
$ftpObj->connect($ftpString);
|
140 |
+
$cfgFile = "connect.cfg";
|
141 |
+
|
142 |
+
$wd = $ftpObj->getcwd();
|
143 |
+
$remoteConfigExists = $ftpObj->fileExists($cfgFile);
|
144 |
+
$tempConfigFile = uniqid($cfgFile."_temp");
|
145 |
+
if(!$remoteConfigExists) {
|
146 |
+
$remoteCfg = new Mage_Connect_Config($tempConfigFile);
|
147 |
+
$remoteCfg->store();
|
148 |
+
$ftpObj->upload($cfgFile, $tempConfigFile);
|
149 |
+
} else {
|
150 |
+
$ftpObj->get($tempConfigFile, $cfgFile);
|
151 |
+
$remoteCfg = new Mage_Connect_Config($tempConfigFile);
|
152 |
+
}
|
153 |
+
$ftpObj->chdir($wd);
|
154 |
+
return array($remoteCfg, $ftpObj);
|
155 |
+
}
|
156 |
+
|
157 |
+
public function writeToRemoteCache($cache, $ftpObj)
|
158 |
+
{
|
159 |
+
$wd = $ftpObj->getcwd();
|
160 |
+
$ftpObj->upload("cache.cfg", $cache->getFilename());
|
161 |
+
@unlink($cache->getFilename());
|
162 |
+
$ftpObj->chdir($wd);
|
163 |
+
}
|
164 |
+
|
165 |
+
public function writeToRemoteConfig($cache, $ftpObj)
|
166 |
+
{
|
167 |
+
$wd = $ftpObj->getcwd();
|
168 |
+
$ftpObj->upload("connect.cfg", $cache->getFilename());
|
169 |
+
@unlink($cache->getFilename());
|
170 |
+
$ftpObj->chdir($wd);
|
171 |
+
}
|
172 |
+
|
173 |
+
/**
|
174 |
+
*
|
175 |
+
* @param $chanName
|
176 |
+
* @param $package
|
177 |
+
* @param Mage_Connect_Singleconfig $cacheObj
|
178 |
+
* @param $ftp
|
179 |
+
* @return unknown_type
|
180 |
+
*/
|
181 |
+
public function processUninstallPackage($chanName, $package, $cacheObj, $configObj)
|
182 |
+
{
|
183 |
+
$package = $cacheObj->getPackageObject($chanName, $package);
|
184 |
+
$contents = $package->getContents();
|
185 |
+
|
186 |
+
$targetPath = rtrim($configObj->magento_root, "\\/");
|
187 |
+
foreach($contents as $file) {
|
188 |
+
$fileName = basename($file);
|
189 |
+
$filePath = dirname($file);
|
190 |
+
$dest = $targetPath . DIRECTORY_SEPARATOR . $filePath . DIRECTORY_SEPARATOR . $fileName;
|
191 |
+
if(@file_exists($dest)) {
|
192 |
+
//var_dump($dest);
|
193 |
+
@unlink($dest);
|
194 |
+
}
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
*
|
200 |
+
* @param $chanName
|
201 |
+
* @param $package
|
202 |
+
* @param Mage_Connect_Singleconfig $cacheObj
|
203 |
+
* @param Mage_Connect_Ftp $ftp
|
204 |
+
* @return unknown_type
|
205 |
+
*/
|
206 |
+
public function processUninstallPackageFtp($chanName, $package, $cacheObj, $ftp)
|
207 |
+
{
|
208 |
+
$ftpDir = $ftp->getcwd();
|
209 |
+
$package = $cacheObj->getPackageObject($chanName, $package);
|
210 |
+
$contents = $package->getContents();
|
211 |
+
foreach($contents as $file) {
|
212 |
+
$res = $ftp->delete($file);
|
213 |
+
}
|
214 |
+
$ftp->chdir($ftpDir);
|
215 |
+
}
|
216 |
+
|
217 |
+
protected function convertFtpPath($str)
|
218 |
+
{
|
219 |
+
return str_replace("\\", "/", $str);
|
220 |
+
}
|
221 |
+
|
222 |
+
public function processInstallPackageFtp($package, $file, $configObj, $ftp)
|
223 |
+
{
|
224 |
+
$ftpDir = $ftp->getcwd();
|
225 |
+
$contents = $package->getContents();
|
226 |
+
$arc = $this->getArchiver();
|
227 |
+
$target = dirname($file).DS.$package->getReleaseFilename();
|
228 |
+
@mkdir($target, 0777, true);
|
229 |
+
$mode = $configObj->global_dir_mode;
|
230 |
+
$tar = $arc->unpack($file, $target);
|
231 |
+
$modeFile = $configObj->global_file_mode;
|
232 |
+
$modeDir = $configObj->global_dir_mode;
|
233 |
+
foreach($contents as $file) {
|
234 |
+
$fileName = basename($file);
|
235 |
+
$filePath = $this->convertFtpPath(dirname($file));
|
236 |
+
$source = $tar.DS.$file;
|
237 |
+
if (file_exists($source) && is_file($source)) {
|
238 |
+
$args = array(ltrim($file,"/"), $source);
|
239 |
+
if($modeDir) {
|
240 |
+
$args[] = $modeDir;
|
241 |
+
}
|
242 |
+
call_user_func_array(array($ftp,'upload'), $args);
|
243 |
+
}
|
244 |
+
}
|
245 |
+
$ftp->chdir($ftpDir);
|
246 |
+
Mage_System_Dirs::rm(array("-r",$target));
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* Package installation to FS
|
251 |
+
* @param Mage_Connect_Package $package
|
252 |
+
* @param string $file
|
253 |
+
* @return void
|
254 |
+
* @throws Exception
|
255 |
+
*/
|
256 |
+
public function processInstallPackage($package, $file, $configObj)
|
257 |
+
{
|
258 |
+
$contents = $package->getContents();
|
259 |
+
$arc = $this->getArchiver();
|
260 |
+
$target = dirname($file).DS.$package->getReleaseFilename();
|
261 |
+
@mkdir($target, 0777, true);
|
262 |
+
$mode = $configObj->global_dir_mode;
|
263 |
+
$tar = $arc->unpack($file, $target);
|
264 |
+
$modeFile = $configObj->global_file_mode;
|
265 |
+
$modeDir = $configObj->global_dir_mode;
|
266 |
+
foreach($contents as $file) {
|
267 |
+
$fileName = basename($file);
|
268 |
+
$filePath = dirname($file);
|
269 |
+
$source = $tar.DS.$file;
|
270 |
+
$targetPath = rtrim($configObj->magento_root, "\\/");
|
271 |
+
@mkdir($targetPath. DS . $filePath, $modeDir, true);
|
272 |
+
$dest = $targetPath . DS . $filePath . DS . $fileName;
|
273 |
+
if (is_file($source)) {
|
274 |
+
@copy($source, $dest);
|
275 |
+
if($modeFile) {
|
276 |
+
@chmod($dest, $modeFile);
|
277 |
+
}
|
278 |
+
} else {
|
279 |
+
@mkdir($dest, $modeDir);
|
280 |
+
}
|
281 |
+
}
|
282 |
+
Mage_System_Dirs::rm(array("-r",$target));
|
283 |
+
}
|
284 |
+
|
285 |
+
|
286 |
+
/**
|
287 |
+
* Get local modified files
|
288 |
+
* @param $chanName
|
289 |
+
* @param $package
|
290 |
+
* @param $cacheObj
|
291 |
+
* @param $configObj
|
292 |
+
* @return array
|
293 |
+
*/
|
294 |
+
public function getLocalModifiedFiles($chanName, $package, $cacheObj, $configObj)
|
295 |
+
{
|
296 |
+
$p = $cachObj->getPackageObject($chanName, $package);
|
297 |
+
$hashContents = $p->getHashContents();
|
298 |
+
$listModified = array();
|
299 |
+
foreach ($hashContents as $file=>$hash) {
|
300 |
+
if (md5_file($configObj->magento_root . DS . $file)!==$hash) {
|
301 |
+
$listModified[] = $file;
|
302 |
+
}
|
303 |
+
}
|
304 |
+
return $listModified;
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Get remote modified files
|
309 |
+
*
|
310 |
+
* @param $chanName
|
311 |
+
* @param $package
|
312 |
+
* @param $cacheObj
|
313 |
+
* @param Mage_Connect_Ftp $ftp
|
314 |
+
* @return array
|
315 |
+
*/
|
316 |
+
public function getRemoteModifiedFiles($chanName, $package, $cacheObj, $ftp)
|
317 |
+
{
|
318 |
+
$p = $cacheObj->getPackageObject($chanName, $package);
|
319 |
+
$hashContents = $p->getHashContents();
|
320 |
+
$listModified = array();
|
321 |
+
foreach ($hashContents as $file=>$hash) {
|
322 |
+
$localFile = uniqid("temp_remote_");
|
323 |
+
if(!$ftp->fileExists($file)) {
|
324 |
+
continue;
|
325 |
+
}
|
326 |
+
$ftp->get($localFile, $file);
|
327 |
+
if (file_exists($localFile) && md5_file($localFile)!==$hash) {
|
328 |
+
$listModified[] = $file;
|
329 |
+
}
|
330 |
+
@unlink($localFile);
|
331 |
+
}
|
332 |
+
return $listModified;
|
333 |
+
}
|
334 |
+
|
335 |
+
|
336 |
+
/**
|
337 |
+
*
|
338 |
+
* Get upgrades list
|
339 |
+
*
|
340 |
+
* @param string/array $channels
|
341 |
+
* @param Mage_Connect_Singleconfig $cacheObject
|
342 |
+
* @param Mage_Connect_Rest $restObj optional
|
343 |
+
* @param bool $checkConflicts
|
344 |
+
* @return array
|
345 |
+
*/
|
346 |
+
public function getUpgradesList($channels, $cacheObject, $configObj, $restObj = null, $checkConflicts = false)
|
347 |
+
{
|
348 |
+
if(is_scalar($channels)) {
|
349 |
+
$channels = array($channels);
|
350 |
+
}
|
351 |
+
|
352 |
+
if(!$restObj) {
|
353 |
+
$restObj = new Mage_Connect_Rest();
|
354 |
+
}
|
355 |
+
|
356 |
+
$updates = array();
|
357 |
+
foreach($channels as $chan) {
|
358 |
+
|
359 |
+
if(!$cacheObject->isChannel($chan)) {
|
360 |
+
continue;
|
361 |
+
}
|
362 |
+
$chanName = $cacheObject->chanName($chan);
|
363 |
+
$localPackages = $cacheObject->getInstalledPackages($chanName);
|
364 |
+
$localPackages = $localPackages[$chanName];
|
365 |
+
|
366 |
+
if(!count($localPackages)) {
|
367 |
+
continue;
|
368 |
+
}
|
369 |
+
|
370 |
+
$channel = $cacheObject->getChannel($chan);
|
371 |
+
$uri = $channel[Mage_Connect_Singleconfig::K_URI];
|
372 |
+
$restObj->setChannel($uri);
|
373 |
+
$remotePackages = $restObj->getPackagesHashed();
|
374 |
+
|
375 |
+
/**
|
376 |
+
* Iterate packages of channel $chan
|
377 |
+
*/
|
378 |
+
$state = $configObj->preferred_state ? $configObj->preferred_state : "devel";
|
379 |
+
|
380 |
+
foreach($localPackages as $localName=>$localData) {
|
381 |
+
if(!isset($remotePackages[$localName])) {
|
382 |
+
continue;
|
383 |
+
}
|
384 |
+
$package = $remotePackages[$localName];
|
385 |
+
$neededToUpgrade = false;
|
386 |
+
$remoteVersion = $localVersion = trim($localData[Mage_Connect_Singleconfig::K_VER]);
|
387 |
+
foreach($package as $version => $s) {
|
388 |
+
|
389 |
+
if( $cacheObject->compareStabilities($s, $state) < 0 ) {
|
390 |
+
continue;
|
391 |
+
}
|
392 |
+
|
393 |
+
if(version_compare($version, $localVersion, ">")) {
|
394 |
+
$neededToUpgrade = true;
|
395 |
+
$remoteVersion = $version;
|
396 |
+
}
|
397 |
+
|
398 |
+
if($checkConflicts) {
|
399 |
+
$conflicts = $cacheObject->hasConflicts($chanName, $localName, $remoteVersion);
|
400 |
+
if(false !== $conflicts) {
|
401 |
+
$neededToUpgrade = false;
|
402 |
+
}
|
403 |
+
}
|
404 |
+
}
|
405 |
+
if(!$neededToUpgrade) {
|
406 |
+
continue;
|
407 |
+
}
|
408 |
+
if(!isset($updates[$chanName])) {
|
409 |
+
$updates[$chanName] = array();
|
410 |
+
}
|
411 |
+
$updates[$chanName][$localName] = array("from"=>$localVersion, "to"=>$remoteVersion);
|
412 |
+
}
|
413 |
+
}
|
414 |
+
return $updates;
|
415 |
+
}
|
416 |
+
|
417 |
+
/**
|
418 |
+
* Get uninstall list
|
419 |
+
* @param string $chanName
|
420 |
+
* @param string $package
|
421 |
+
* @param Mage_Connect_Singleconfig $cache
|
422 |
+
* @param Mage_Connect_Config $config
|
423 |
+
* @param bool $withDepsRecursive
|
424 |
+
* @return array
|
425 |
+
*/
|
426 |
+
public function getUninstallList($chanName, $package, $cache, $config, $withDepsRecursive = true)
|
427 |
+
{
|
428 |
+
static $level = 0;
|
429 |
+
static $hash = array();
|
430 |
+
|
431 |
+
$chanName = $cache->chanName($chanName);
|
432 |
+
$keyOuter = $chanName . "/" . $package;
|
433 |
+
$level++;
|
434 |
+
|
435 |
+
try {
|
436 |
+
$chanName = $cache->chanName($chanName);
|
437 |
+
if(!$cache->hasPackage($chanName, $package)) {
|
438 |
+
$level--;
|
439 |
+
if($level == 0) {
|
440 |
+
$hash = array();
|
441 |
+
return array('list'=>array());
|
442 |
+
}
|
443 |
+
return;
|
444 |
+
}
|
445 |
+
$dependencies = $cache->getPackageDependencies($chanName, $package);
|
446 |
+
$data = $cache->getPackage($chanName, $package);
|
447 |
+
$version = $data['version'];
|
448 |
+
$keyOuter = $chanName . "/" . $package;
|
449 |
+
|
450 |
+
//print "Processing outer: {$keyOuter} \n";
|
451 |
+
$hash[$keyOuter] = array (
|
452 |
+
'name' => $package,
|
453 |
+
'channel' => $chanName,
|
454 |
+
'version' => $version,
|
455 |
+
'packages' => $dependencies,
|
456 |
+
);
|
457 |
+
|
458 |
+
if($withDepsRecursive) {
|
459 |
+
$flds = array('name','channel','min','max');
|
460 |
+
$fldsCount = count($flds);
|
461 |
+
foreach($dependencies as $row) {
|
462 |
+
foreach($flds as $key) {
|
463 |
+
$varName = "p".ucfirst($key);
|
464 |
+
$$varName = $row[$key];
|
465 |
+
}
|
466 |
+
$method = __FUNCTION__;
|
467 |
+
$keyInner = $pChannel . "/" . $pName;
|
468 |
+
if(!isset($hash[$keyInner])) {
|
469 |
+
$this->$method($pChannel, $pName, $cache, $config,
|
470 |
+
$withDepsRecursive, false);
|
471 |
+
}
|
472 |
+
}
|
473 |
+
}
|
474 |
+
|
475 |
+
} catch (Exception $e) {
|
476 |
+
//$this->_failed[] = array('name'=>$package, 'channel'=>$chanName, 'max'=>$versionMax, 'min'=>$versionMin, 'reason'=>$e->getMessage());
|
477 |
+
}
|
478 |
+
|
479 |
+
$level--;
|
480 |
+
if(0 === $level) {
|
481 |
+
$out = $this->processDepsHash($hash);
|
482 |
+
$hash = array();
|
483 |
+
return array('list'=>$out);
|
484 |
+
}
|
485 |
+
}
|
486 |
+
|
487 |
+
/**
|
488 |
+
* Get dependencies list/install order info
|
489 |
+
*
|
490 |
+
*
|
491 |
+
* @param string $chanName
|
492 |
+
* @param string $package
|
493 |
+
* @param Mage_Connect_Singleconfig $cache
|
494 |
+
* @param Mage_Connect_Config $config
|
495 |
+
* @param mixed $versionMax
|
496 |
+
* @param mixed $versionMin
|
497 |
+
* @return mixed
|
498 |
+
*/
|
499 |
+
public function getDependenciesList( $chanName, $package, $cache, $config, $versionMax = false, $versionMin = false, $withDepsRecursive = true, $forceRemote = false)
|
500 |
+
{
|
501 |
+
|
502 |
+
static $level = 0;
|
503 |
+
static $_depsHash = array();
|
504 |
+
static $_deps = array();
|
505 |
+
static $_failed = array();
|
506 |
+
|
507 |
+
$level++;
|
508 |
+
|
509 |
+
try {
|
510 |
+
$chanName = $cache->chanName($chanName);
|
511 |
+
|
512 |
+
$rest = new Mage_Connect_Rest($config->protocol);
|
513 |
+
$rest->setChannel($cache->chanUrl($chanName));
|
514 |
+
$releases = $rest->getReleases($package);
|
515 |
+
if(!$releases || !count($releases)) {
|
516 |
+
throw new Exception("No releases for: '{$package}', skipping");
|
517 |
+
}
|
518 |
+
$state = $config->preffered_state ? $confg->preffered_state : 'devel';
|
519 |
+
$version = $cache->detectVersionFromRestArray($releases, $versionMin, $versionMax, $state);
|
520 |
+
if(!$version) {
|
521 |
+
throw new Exception("Version for '{$package}' was not detected");
|
522 |
+
}
|
523 |
+
$packageInfo = $rest->getPackageReleaseInfo($package, $version);
|
524 |
+
if(false === $packageInfo) {
|
525 |
+
throw new Exception("Package release '{$package}' not found on server");
|
526 |
+
}
|
527 |
+
unset($rest);
|
528 |
+
$dependencies = $packageInfo->getDependencyPackages();
|
529 |
+
$keyOuter = $chanName . "/" . $package;
|
530 |
+
|
531 |
+
//print "Processing outer: {$keyOuter} \n";
|
532 |
+
$_depsHash[$keyOuter] = array (
|
533 |
+
'name' => $package,
|
534 |
+
'channel' => $chanName,
|
535 |
+
'downloaded_version' => $version,
|
536 |
+
'min' => $versionMin,
|
537 |
+
'max' => $versionMax,
|
538 |
+
'packages' => $dependencies,
|
539 |
+
);
|
540 |
+
|
541 |
+
if($withDepsRecursive) {
|
542 |
+
$flds = array('name','channel','min','max');
|
543 |
+
$fldsCount = count($flds);
|
544 |
+
foreach($dependencies as $row) {
|
545 |
+
foreach($flds as $key) {
|
546 |
+
$varName = "p".ucfirst($key);
|
547 |
+
$$varName = $row[$key];
|
548 |
+
}
|
549 |
+
$method = __FUNCTION__;
|
550 |
+
$keyInner = $pChannel . "/" . $pName;
|
551 |
+
if(!isset($_depsHash[$keyInner])) {
|
552 |
+
$_deps[] = $row;
|
553 |
+
$this->$method($pChannel, $pName, $cache, $config,
|
554 |
+
$pMax, $pMin, $withDepsRecursive, $forceRemote, false);
|
555 |
+
} else {
|
556 |
+
$downloaded = $_depsHash[$keyInner]['downloaded_version'];
|
557 |
+
$hasMin = $_depsHash[$keyInner]['min'];
|
558 |
+
$hasMax = $_depsHash[$keyInner]['max'];
|
559 |
+
if($pMin === $hasMin && $pMax === $hasMax) {
|
560 |
+
//var_dump("Equal requirements, skipping");
|
561 |
+
continue;
|
562 |
+
}
|
563 |
+
|
564 |
+
if($cache->versionInRange($downloaded, $pMin, $pMax)) {
|
565 |
+
//var_dump("Downloaded package matches new range too");
|
566 |
+
continue;
|
567 |
+
}
|
568 |
+
|
569 |
+
$names = array("pMin","pMax","hasMin","hasMax");
|
570 |
+
for($i=0, $c=count($names); $i<$c; $i++) {
|
571 |
+
if(!isset($$names[$i])) {
|
572 |
+
continue;
|
573 |
+
}
|
574 |
+
if(false !== $$names[$i]) {
|
575 |
+
continue;
|
576 |
+
}
|
577 |
+
$$names[$i] = $i % 2 == 0 ? "0" : "999999999";
|
578 |
+
}
|
579 |
+
|
580 |
+
if(!$cache->hasVersionRangeIntersect($pMin,$pMax, $hasMin, $hasMax)) {
|
581 |
+
$reason = "Detected {$pName} conflict of versions: {$hasMin}-{$hasMax} and {$pMin}-{$pMax}";
|
582 |
+
unset($_depsHash[$keyInner]);
|
583 |
+
$_failed[] = array('name'=>$pName, 'channel'=>$pChannel, 'max'=>$pMax, 'min'=>$pMin, 'reason'=>$reason);
|
584 |
+
continue;
|
585 |
+
}
|
586 |
+
$newMaxIsLess = version_compare($pMax, $hasMax, "<");
|
587 |
+
$newMinIsGreater = version_compare($pMin, $hasMin, ">");
|
588 |
+
$forceMax = $newMaxIsLess ? $pMax : $hasMax;
|
589 |
+
$forceMin = $newMinIsGreater ? $pMin : $hasMin;
|
590 |
+
//var_dump("Trying to process {$pName} : max {$forceMax} - min {$forceMin}");
|
591 |
+
$this->$method($pChannel, $pName, $cache, $config,
|
592 |
+
$forceMax, $forceMin, $withDepsRecursive, $forceRemote);
|
593 |
+
}
|
594 |
+
}
|
595 |
+
}
|
596 |
+
} catch (Exception $e) {
|
597 |
+
$_failed[] = array('name'=>$package, 'channel'=>$chanName, 'max'=>$versionMax, 'min'=>$versionMin, 'reason'=>$e->getMessage());
|
598 |
+
}
|
599 |
+
|
600 |
+
|
601 |
+
$level--;
|
602 |
+
if($level == 0) {
|
603 |
+
$out = $this->processDepsHash($_depsHash);
|
604 |
+
$deps = $_deps;
|
605 |
+
$failed = $_failed;
|
606 |
+
$_depsHash = array();
|
607 |
+
$_deps = array();
|
608 |
+
$_failed = array();
|
609 |
+
return array('deps' => $deps, 'result' => $out, 'failed'=> $failed);
|
610 |
+
}
|
611 |
+
|
612 |
+
}
|
613 |
+
|
614 |
+
|
615 |
+
/**
|
616 |
+
* Process dependencies hash
|
617 |
+
* Makes topological sorting and gives operation order list
|
618 |
+
*
|
619 |
+
* @param array $depsHash
|
620 |
+
* @param bool $sortReverse
|
621 |
+
* @return array
|
622 |
+
*/
|
623 |
+
protected function processDepsHash(&$depsHash, $sortReverse = true)
|
624 |
+
{
|
625 |
+
$nodes = array();
|
626 |
+
$graph = new Mage_Connect_Structures_Graph();
|
627 |
+
|
628 |
+
foreach($depsHash as $key=>$data) {
|
629 |
+
$packages = $data['packages'];
|
630 |
+
$node = new Mage_Connect_Structures_Node();
|
631 |
+
$nodes[$key] =& $node;
|
632 |
+
unset($data['packages']);
|
633 |
+
$node->setData($data);
|
634 |
+
$graph->addNode($node);
|
635 |
+
unset($node);
|
636 |
+
}
|
637 |
+
|
638 |
+
if(count($nodes) > 1) {
|
639 |
+
foreach($depsHash as $key=>$data) {
|
640 |
+
$packages = $data['packages'];
|
641 |
+
foreach($packages as $pdata) {
|
642 |
+
$pName = $pdata['channel'] . "/" . $pdata['name'];
|
643 |
+
if(isset($nodes[$key], $nodes[$pName])) {
|
644 |
+
$nodes[$key]->connectTo($nodes[$pName]);
|
645 |
+
}
|
646 |
+
}
|
647 |
+
}
|
648 |
+
}
|
649 |
+
$result = $graph->topologicalSort();
|
650 |
+
$sortReverse ? krsort($result) : ksort($result);
|
651 |
+
$out = array();
|
652 |
+
$total = 0;
|
653 |
+
foreach($result as $order=>$nodes) {
|
654 |
+
foreach($nodes as $n) {
|
655 |
+
$out[] = $n->getData();
|
656 |
+
}
|
657 |
+
}
|
658 |
+
unset($graph, $nodes);
|
659 |
+
return $out;
|
660 |
+
}
|
661 |
+
|
662 |
+
}
|
lib/Mage/Connect/Repository.php
ADDED
File without changes
|
lib/Mage/Connect/Repository/Abstract.php
ADDED
File without changes
|
lib/Mage/Connect/Repository/Channel.php
ADDED
File without changes
|
lib/Mage/Connect/Repository/Channel/Abstract.php
ADDED
File without changes
|
lib/Mage/Connect/Repository/Channel/Commercial.php
ADDED
File without changes
|
lib/Mage/Connect/Repository/Channel/Community.php
ADDED
File without changes
|
lib/Mage/Connect/Repository/Channel/Core.php
ADDED
File without changes
|
lib/Mage/Connect/Repository/Local.php
ADDED
File without changes
|
lib/Mage/Connect/Rest.php
ADDED
@@ -0,0 +1,364 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with remote REST interface
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
|
35 |
+
class Mage_Connect_Rest
|
36 |
+
{
|
37 |
+
|
38 |
+
const CHANNELS_XML = "channels.xml";
|
39 |
+
const CHANNEL_XML = "channel.xml";
|
40 |
+
const PACKAGES_XML = "packages.xml";
|
41 |
+
const RELEASES_XML = "releases.xml";
|
42 |
+
const PACKAGE_XML = "package.xml";
|
43 |
+
const EXT = "tgz";
|
44 |
+
|
45 |
+
/**
|
46 |
+
* HTTP Loader
|
47 |
+
* @var Mage_HTTP_IClient
|
48 |
+
*/
|
49 |
+
protected $_loader = null;
|
50 |
+
|
51 |
+
|
52 |
+
/**
|
53 |
+
* XML parser
|
54 |
+
* @var Mage_Xml_Parser
|
55 |
+
*/
|
56 |
+
protected $_parser = null;
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Channel URI
|
60 |
+
* @var string
|
61 |
+
*/
|
62 |
+
protected $_chanUri = '';
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Protocol HTTP or FTP
|
66 |
+
*
|
67 |
+
* @var string http or ftp
|
68 |
+
*/
|
69 |
+
protected $_protocol = '';
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Constructor
|
73 |
+
*/
|
74 |
+
public function __construct($protocol="http")
|
75 |
+
{
|
76 |
+
switch ($protocol) {
|
77 |
+
case 'http':default:
|
78 |
+
$this->_protocol = 'http';
|
79 |
+
break;
|
80 |
+
case 'ftp':
|
81 |
+
$this->_protocol = 'ftp';
|
82 |
+
break;
|
83 |
+
}
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Set channel info
|
88 |
+
*
|
89 |
+
* @param string $uri
|
90 |
+
* @param sting $name
|
91 |
+
*/
|
92 |
+
public function setChannel($uri)
|
93 |
+
{
|
94 |
+
$this->_chanUri = $uri;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Get HTTP loader
|
99 |
+
* @return Mage_Connect_Loader
|
100 |
+
*/
|
101 |
+
protected function getLoader()
|
102 |
+
{
|
103 |
+
if(is_null($this->_loader)) {
|
104 |
+
$this->_loader = Mage_Connect_Loader::getInstance($this->_protocol);
|
105 |
+
}
|
106 |
+
return $this->_loader;
|
107 |
+
}
|
108 |
+
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Get parser
|
112 |
+
*
|
113 |
+
* @return Mage_Xml_Parser
|
114 |
+
*/
|
115 |
+
protected function getParser()
|
116 |
+
{
|
117 |
+
if(is_null($this->_parser)) {
|
118 |
+
$this->_parser = new Mage_Xml_Parser();
|
119 |
+
}
|
120 |
+
return $this->_parser;
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Load URI response
|
125 |
+
* @param string $uri
|
126 |
+
*/
|
127 |
+
protected function loadChannelUri($uriSuffix)
|
128 |
+
{
|
129 |
+
$url = $this->_chanUri."/".$uriSuffix;
|
130 |
+
//print $url."\n";
|
131 |
+
$this->getLoader()->get($url);
|
132 |
+
$statusCode = $this->getLoader()->getStatus();
|
133 |
+
if($statusCode != 200) {
|
134 |
+
return false;
|
135 |
+
}
|
136 |
+
return $this->getLoader()->getBody();
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Get channels list of URI
|
141 |
+
* @return array
|
142 |
+
*/
|
143 |
+
public function getChannelInfo()
|
144 |
+
{
|
145 |
+
$out = $this->loadChannelUri(self::CHANNEL_XML);
|
146 |
+
$statusCode = $this->getLoader()->getStatus();
|
147 |
+
if($statusCode != 200) {
|
148 |
+
throw new Exception("Invalid server response for {$this->_chanUri}");
|
149 |
+
}
|
150 |
+
$parser = $this->getParser();
|
151 |
+
$out = $parser->loadXML($out)->xmlToArray();
|
152 |
+
|
153 |
+
// TODO: add channel validator
|
154 |
+
$vo = new Mage_Connect_Channel_VO();
|
155 |
+
$vo->fromArray($out['channel']);
|
156 |
+
if(!$vo->validate()) {
|
157 |
+
throw new Exception("Invalid channel.xml file");
|
158 |
+
}
|
159 |
+
return $vo;
|
160 |
+
}
|
161 |
+
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Get packages list of channel
|
165 |
+
* @return array
|
166 |
+
*/
|
167 |
+
public function getPackages()
|
168 |
+
{
|
169 |
+
$out = $this->loadChannelUri(self::PACKAGES_XML);
|
170 |
+
$statusCode = $this->getLoader()->getStatus();
|
171 |
+
if($statusCode != 200) {
|
172 |
+
return false;
|
173 |
+
}
|
174 |
+
$parser = $this->getParser();
|
175 |
+
$out = $parser->loadXML($out)->xmlToArray();
|
176 |
+
|
177 |
+
|
178 |
+
if(!isset($out['data']['p'])) {
|
179 |
+
return array();
|
180 |
+
}
|
181 |
+
if(isset($out['data']['p'][0])) {
|
182 |
+
return $out['data']['p'];
|
183 |
+
}
|
184 |
+
if(is_array($out['data']['p'])) {
|
185 |
+
return array($out['data']['p']);
|
186 |
+
}
|
187 |
+
return array();
|
188 |
+
}
|
189 |
+
|
190 |
+
|
191 |
+
public function getPackagesHashed()
|
192 |
+
{
|
193 |
+
$out = $this->loadChannelUri(self::PACKAGES_XML);
|
194 |
+
$statusCode = $this->getLoader()->getStatus();
|
195 |
+
if($statusCode != 200) {
|
196 |
+
return false;
|
197 |
+
}
|
198 |
+
$parser = $this->getParser();
|
199 |
+
$out = $parser->loadXML($out)->xmlToArray();
|
200 |
+
|
201 |
+
$return = array();
|
202 |
+
if(!isset($out['data']['p'])) {
|
203 |
+
return $return;
|
204 |
+
}
|
205 |
+
if(isset($out['data']['p'][0])) {
|
206 |
+
$return = $out['data']['p'];
|
207 |
+
}
|
208 |
+
if(is_array($out['data']['p'])) {
|
209 |
+
$return = array($out['data']['p']);
|
210 |
+
}
|
211 |
+
$c = count($return);
|
212 |
+
if($c) {
|
213 |
+
$output = array();
|
214 |
+
for($i=0,$c=count($return[0]); $i<$c; $i++) {
|
215 |
+
$element = $return[0][$i];
|
216 |
+
$output[$element['n']] = $element['r'];
|
217 |
+
}
|
218 |
+
$return = $output;
|
219 |
+
}
|
220 |
+
|
221 |
+
$out = array();
|
222 |
+
foreach($return as $name=>$package) {
|
223 |
+
$stabilities = array_map(array($this, 'shortStateToLong'), array_keys($package));
|
224 |
+
$versions = array_map('trim', array_values($package));
|
225 |
+
$package = array_combine($versions, $stabilities);
|
226 |
+
ksort($package);
|
227 |
+
$out[$name] = $package;
|
228 |
+
}
|
229 |
+
return $out;
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* Stub
|
234 |
+
* @param $n
|
235 |
+
* @return unknown_type
|
236 |
+
*/
|
237 |
+
public function escapePackageName($n)
|
238 |
+
{
|
239 |
+
return $n;
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Get releases list of package on current channel
|
244 |
+
* @param string $package package name
|
245 |
+
*/
|
246 |
+
public function getReleases($package)
|
247 |
+
{
|
248 |
+
$out = $this->loadChannelUri($this->escapePackageName($package)."/".self::RELEASES_XML);
|
249 |
+
$statusCode = $this->getLoader()->getStatus();
|
250 |
+
if($statusCode != 200) {
|
251 |
+
return false;
|
252 |
+
}
|
253 |
+
$parser = $this->getParser();
|
254 |
+
$out = $parser->loadXML($out)->xmlToArray();
|
255 |
+
if(!isset($out['releases']['r'])) {
|
256 |
+
return array();
|
257 |
+
}
|
258 |
+
$src = $out['releases']['r'];
|
259 |
+
if(!array_key_exists(0, $src)) {
|
260 |
+
return array($src);
|
261 |
+
}
|
262 |
+
$this->sortReleases($src);
|
263 |
+
return $src;
|
264 |
+
}
|
265 |
+
|
266 |
+
/**
|
267 |
+
* Sort releases
|
268 |
+
* @param array $releases
|
269 |
+
* @return void
|
270 |
+
*/
|
271 |
+
public function sortReleases(array &$releases)
|
272 |
+
{
|
273 |
+
usort($releases, array($this, 'sortReleasesCallback'));
|
274 |
+
$releases = array_reverse($releases);
|
275 |
+
}
|
276 |
+
|
277 |
+
/**
|
278 |
+
* Sort releases callback
|
279 |
+
* @param string $a
|
280 |
+
* @param srting $b
|
281 |
+
* @return int
|
282 |
+
*/
|
283 |
+
protected function sortReleasesCallback($a, $b)
|
284 |
+
{
|
285 |
+
return version_compare($a['v'],$b['v']);
|
286 |
+
}
|
287 |
+
|
288 |
+
/**
|
289 |
+
* Get package info (package.xml)
|
290 |
+
*
|
291 |
+
* @param $package
|
292 |
+
* @return unknown_type
|
293 |
+
*/
|
294 |
+
public function getPackageInfo($package)
|
295 |
+
{
|
296 |
+
$out = $this->loadChannelUri($this->escapePackageName($package)."/".self::PACKAGE_XML);
|
297 |
+
if(false === $out) {
|
298 |
+
return false;
|
299 |
+
}
|
300 |
+
return new Mage_Connect_Package($out);
|
301 |
+
}
|
302 |
+
|
303 |
+
/**
|
304 |
+
*
|
305 |
+
* @param $package
|
306 |
+
* @param $version
|
307 |
+
* @return Mage_Connect_Package
|
308 |
+
*/
|
309 |
+
public function getPackageReleaseInfo($package, $version)
|
310 |
+
{
|
311 |
+
$out = $this->loadChannelUri($this->escapePackageName($package)."/".$version."/".self::PACKAGE_XML);
|
312 |
+
if(false === $out) {
|
313 |
+
return false;
|
314 |
+
}
|
315 |
+
return new Mage_Connect_Package($out);
|
316 |
+
}
|
317 |
+
|
318 |
+
/**
|
319 |
+
* Get package archive file of release
|
320 |
+
* @param string $package package name
|
321 |
+
* @param string $version version
|
322 |
+
*/
|
323 |
+
public function downloadPackageFileOfRelease($package, $version, $targetFile)
|
324 |
+
{
|
325 |
+
$package = $this->escapePackageName($package);
|
326 |
+
$version = $this->escapePackageName($version);
|
327 |
+
|
328 |
+
|
329 |
+
if(file_exists($targetFile)) {
|
330 |
+
$chksum = $this->loadChannelUri($package."/".$version."/checksum");
|
331 |
+
$statusCode = $this->getLoader()->getStatus();
|
332 |
+
if($statusCode == 200) {
|
333 |
+
if(md5_file($targetFile) == $chksum) {
|
334 |
+
return true;
|
335 |
+
}
|
336 |
+
}
|
337 |
+
}
|
338 |
+
|
339 |
+
|
340 |
+
$out = $this->loadChannelUri($package."/".$version."/".$package."-".$version.".".self::EXT);
|
341 |
+
|
342 |
+
$statusCode = $this->getLoader()->getStatus();
|
343 |
+
if($statusCode != 200) {
|
344 |
+
throw new Exception("Package not found: {$package} {$version}");
|
345 |
+
}
|
346 |
+
$dir = dirname($targetFile);
|
347 |
+
@mkdir($dir, 0777, true);
|
348 |
+
$result = @file_put_contents($targetFile, $out);
|
349 |
+
if(false === $result) {
|
350 |
+
throw new Exception("Cannot write to file {$targetFile}");
|
351 |
+
}
|
352 |
+
return true;
|
353 |
+
}
|
354 |
+
|
355 |
+
protected $states = array('b'=>'beta', 'd'=>'dev', 's'=>'stable', 'a'=>'alpha');
|
356 |
+
|
357 |
+
public function shortStateToLong($s)
|
358 |
+
{
|
359 |
+
return isset($this->states[$s]) ? $this->states[$s] : 'dev';
|
360 |
+
}
|
361 |
+
|
362 |
+
|
363 |
+
}
|
364 |
+
|
lib/Mage/Connect/Singleconfig.php
ADDED
@@ -0,0 +1,865 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to manipulate with channel/package cache file
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
|
35 |
+
class Mage_Connect_Singleconfig
|
36 |
+
{
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Cache data
|
40 |
+
* @var array
|
41 |
+
*/
|
42 |
+
protected $_data = array();
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Filename
|
46 |
+
* @var string
|
47 |
+
*/
|
48 |
+
protected $_readFilename = false;
|
49 |
+
|
50 |
+
/**
|
51 |
+
*
|
52 |
+
* @var unknown_type
|
53 |
+
*/
|
54 |
+
protected $_debug = false;
|
55 |
+
|
56 |
+
/**
|
57 |
+
*
|
58 |
+
* @var unknown_type
|
59 |
+
*/
|
60 |
+
protected $_validator;
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Internal keys constants
|
64 |
+
*/
|
65 |
+
const K_CHAN = 'channels_by_name';
|
66 |
+
const K_CHAN_URI = 'channels_by_uri';
|
67 |
+
const K_CHAN_ALIAS = 'channel_aliases';
|
68 |
+
const K_PACK = 'packages';
|
69 |
+
const K_URI = 'uri';
|
70 |
+
const K_CHAN_DATA = 'channel_data';
|
71 |
+
const K_NAME = 'name';
|
72 |
+
const K_VER = 'version';
|
73 |
+
const K_STATE = 'stability';
|
74 |
+
const K_XML = 'xml';
|
75 |
+
const K_DEPS = 'deps';
|
76 |
+
const K_PACK_DEPS = 'pack_deps';
|
77 |
+
const K_CONFIG = 'config';
|
78 |
+
|
79 |
+
public function getValidUri($str)
|
80 |
+
{
|
81 |
+
$data = @parse_url($str);
|
82 |
+
if(isset($data['path'])) {
|
83 |
+
return $data['path'];
|
84 |
+
}
|
85 |
+
return false;
|
86 |
+
}
|
87 |
+
|
88 |
+
public function getFilename()
|
89 |
+
{
|
90 |
+
return $this->_readFilename;
|
91 |
+
}
|
92 |
+
|
93 |
+
public function formatUri($uri)
|
94 |
+
{
|
95 |
+
$uri = rtrim($uri, "/");
|
96 |
+
$uri = str_replace("http://", '', $uri);
|
97 |
+
$uri = str_replace("ftp://", '', $uri);
|
98 |
+
return $uri;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Get data
|
103 |
+
* @return unknown_type
|
104 |
+
*/
|
105 |
+
public function getData()
|
106 |
+
{
|
107 |
+
return $this->_data;
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Constructor
|
112 |
+
* @param srting $file
|
113 |
+
* @return void
|
114 |
+
*/
|
115 |
+
public function __construct($file = "cache.cfg")
|
116 |
+
{
|
117 |
+
$this->setEmptyConfig();
|
118 |
+
if($file) {
|
119 |
+
$this->_readFilename = $file;
|
120 |
+
$this->load();
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Load cache from file
|
127 |
+
* @param string $file
|
128 |
+
* @return void
|
129 |
+
*/
|
130 |
+
public function load($file = false)
|
131 |
+
{
|
132 |
+
if(false === $file) {
|
133 |
+
$file = $this->_readFilename;
|
134 |
+
}
|
135 |
+
if(false === $file) {
|
136 |
+
return;
|
137 |
+
}
|
138 |
+
|
139 |
+
if(!file_exists($file)) {
|
140 |
+
$this->save($file);
|
141 |
+
return;
|
142 |
+
}
|
143 |
+
|
144 |
+
if(!is_readable($file)) {
|
145 |
+
return $this->doError("File is not readable: '{$file}'");
|
146 |
+
}
|
147 |
+
|
148 |
+
$this->_readFilename = $file;
|
149 |
+
|
150 |
+
$data = @file_get_contents($file);
|
151 |
+
if(false === $data) {
|
152 |
+
return $this->doError("Cannot get file contents: '{$file}'");
|
153 |
+
}
|
154 |
+
|
155 |
+
if(!$this->_debug) {
|
156 |
+
$data = @gzuncompress($data);
|
157 |
+
if(false === $data) {
|
158 |
+
return $this->doError("Cannot unpack gzipped data in file contents: '{$file}'");
|
159 |
+
}
|
160 |
+
}
|
161 |
+
$data = @unserialize($data);
|
162 |
+
if(unserialize(false) === $data) {
|
163 |
+
return $this->doError("Cannot unserialize data in file contents: '{$file}'");
|
164 |
+
}
|
165 |
+
|
166 |
+
|
167 |
+
$validData = true;
|
168 |
+
foreach(array_keys($this->_data) as $k) {
|
169 |
+
if(!isset($data[$k])) {
|
170 |
+
$validData = false;
|
171 |
+
} else {
|
172 |
+
$this->_data[$k] = $data[$k];
|
173 |
+
}
|
174 |
+
}
|
175 |
+
if($validData) {
|
176 |
+
$this->_data = $data;
|
177 |
+
} else {
|
178 |
+
$this->save();
|
179 |
+
}
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Save contents
|
184 |
+
* @param string $file
|
185 |
+
* @return void
|
186 |
+
*/
|
187 |
+
public function save($file = false)
|
188 |
+
{
|
189 |
+
if(false === $file) {
|
190 |
+
$file = $this->_readFilename;
|
191 |
+
}
|
192 |
+
if(false === $file) {
|
193 |
+
return;
|
194 |
+
}
|
195 |
+
$data = @serialize($this->_data);
|
196 |
+
if(!$this->_debug) {
|
197 |
+
$data = @gzcompress($data);
|
198 |
+
}
|
199 |
+
$res = @file_put_contents($file, $data);
|
200 |
+
if(!$res) {
|
201 |
+
$this->doError("Cannot save: '{$file}'");
|
202 |
+
}
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Set empty config skeleton
|
207 |
+
* @return void
|
208 |
+
*/
|
209 |
+
public function setEmptyConfig()
|
210 |
+
{
|
211 |
+
$this->_data = array(
|
212 |
+
self::K_CHAN => array (),
|
213 |
+
self::K_CHAN_URI => array (),
|
214 |
+
self::K_CHAN_ALIAS => array (),
|
215 |
+
);
|
216 |
+
}
|
217 |
+
|
218 |
+
|
219 |
+
public function isChannel($chanName)
|
220 |
+
{
|
221 |
+
if($this->isChannelName($chanName)) {
|
222 |
+
return true;
|
223 |
+
}
|
224 |
+
if($this->isChannelUri($chanName)) {
|
225 |
+
return true;
|
226 |
+
}
|
227 |
+
if($this->isChannelAlias($chanName)) {
|
228 |
+
return true;
|
229 |
+
}
|
230 |
+
return false;
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Get channel
|
235 |
+
* @param string $chanName
|
236 |
+
* @return array
|
237 |
+
*/
|
238 |
+
public function getChannel($chanName)
|
239 |
+
{
|
240 |
+
if($this->isChannelAlias($chanName)) {
|
241 |
+
$chanName = $this->getChannelNameByAlias($chanName);
|
242 |
+
} elseif($this->isChannelUri($chanName)) {
|
243 |
+
$chanName = $this->getChannelUriRecord($chanName);
|
244 |
+
}
|
245 |
+
if($this->isChannelName($chanName)) {
|
246 |
+
return $this->_data[self::K_CHAN][$chanName];
|
247 |
+
}
|
248 |
+
}
|
249 |
+
|
250 |
+
/**
|
251 |
+
* Is channel name?
|
252 |
+
* @param $chanName
|
253 |
+
* @return bool
|
254 |
+
*/
|
255 |
+
public function isChannelName($chanName)
|
256 |
+
{
|
257 |
+
return isset($this->_data[self::K_CHAN][$chanName]);
|
258 |
+
}
|
259 |
+
|
260 |
+
/**
|
261 |
+
* Is channel alias?
|
262 |
+
* @param string $chanName
|
263 |
+
* @return bool
|
264 |
+
*/
|
265 |
+
public function isChannelAlias($chanName)
|
266 |
+
{
|
267 |
+
return isset($this->_data[self::K_CHAN_ALIAS][$chanName]);
|
268 |
+
}
|
269 |
+
|
270 |
+
/**
|
271 |
+
* Is channel uri?
|
272 |
+
* @param $uri
|
273 |
+
* @return bool
|
274 |
+
*/
|
275 |
+
public function isChannelUri($uri)
|
276 |
+
{
|
277 |
+
$uri = $this->formatUri($uri);
|
278 |
+
return isset($this->_data[self::K_CHAN_URI][$uri]);
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
* Unset channel uri record
|
283 |
+
* @param string $uri
|
284 |
+
* @return void
|
285 |
+
*/
|
286 |
+
protected function unsetChannelUriRecord($uri)
|
287 |
+
{
|
288 |
+
$uri = $this->formatUri($uri);
|
289 |
+
unset($this->_data[self::K_CHAN_URI][$uri]);
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* Set channel uri record: uri maps to channel record
|
294 |
+
* @param string $chanName
|
295 |
+
* @param string $uri
|
296 |
+
* @return void
|
297 |
+
*/
|
298 |
+
protected function setChannelUriRecord($chanName, $uri)
|
299 |
+
{
|
300 |
+
$uri = $this->formatUri($uri);
|
301 |
+
$this->_data[self::K_CHAN_URI][$uri] = $chanName;
|
302 |
+
}
|
303 |
+
|
304 |
+
/**
|
305 |
+
* Get channel name by uri record
|
306 |
+
* @param string $uri
|
307 |
+
* @return string
|
308 |
+
*/
|
309 |
+
protected function getChannelUriRecord($uri)
|
310 |
+
{
|
311 |
+
$uri = $this->formatUri($uri);
|
312 |
+
return $this->_data[self::K_CHAN_URI][$uri];
|
313 |
+
}
|
314 |
+
|
315 |
+
|
316 |
+
/**
|
317 |
+
* Unset channel record
|
318 |
+
* @param string $chanName
|
319 |
+
* @return void
|
320 |
+
*/
|
321 |
+
protected function unsetChannelRecord($chanName)
|
322 |
+
{
|
323 |
+
unset($this->_data[self::K_CHAN][$chanName]);
|
324 |
+
}
|
325 |
+
|
326 |
+
/**
|
327 |
+
* Get channel record
|
328 |
+
* @param string $chanName
|
329 |
+
* @return array
|
330 |
+
*/
|
331 |
+
protected function getChannelRecord($chanName)
|
332 |
+
{
|
333 |
+
return $this->_data[self::K_CHAN][$chanName];
|
334 |
+
}
|
335 |
+
|
336 |
+
/**
|
337 |
+
* Set channel record
|
338 |
+
* @param string $chanName
|
339 |
+
* @param string $uri
|
340 |
+
* @param mixed $data
|
341 |
+
* @param array $packages
|
342 |
+
* @return void
|
343 |
+
*/
|
344 |
+
protected function setChannelRecord($chanName, $uri, $data, $packages = array())
|
345 |
+
{
|
346 |
+
$this->_data[self::K_CHAN][$chanName] = array(
|
347 |
+
self::K_NAME=>$chanName,
|
348 |
+
self::K_URI=>$uri,
|
349 |
+
self::K_CHAN_DATA=>$data,
|
350 |
+
self::K_PACK=>$packages
|
351 |
+
);
|
352 |
+
}
|
353 |
+
|
354 |
+
/**
|
355 |
+
* Set package record
|
356 |
+
* @param string $chanName
|
357 |
+
* @param string $packageName
|
358 |
+
* @param mixed $data
|
359 |
+
* @return void
|
360 |
+
*/
|
361 |
+
protected function setPackageRecord($chanName, $packageName, $data, $oneField = null)
|
362 |
+
{
|
363 |
+
if(null === $oneField) {
|
364 |
+
$this->_data[self::K_CHAN][$chanName][self::K_PACK][$packageName] = $data;
|
365 |
+
} else {
|
366 |
+
$this->_data[self::K_CHAN][$chanName][self::K_PACK][$packageName][$oneField] = $data;
|
367 |
+
}
|
368 |
+
}
|
369 |
+
|
370 |
+
|
371 |
+
|
372 |
+
/**
|
373 |
+
* Unset package record
|
374 |
+
* @param string $chanName
|
375 |
+
* @param string $packageName
|
376 |
+
* @return void
|
377 |
+
*/
|
378 |
+
protected function unsetPackageRecord($chanName, $packageName)
|
379 |
+
{
|
380 |
+
unset($this->_data[self::K_CHAN][$chanName][self::K_PACK][$packageName]);
|
381 |
+
}
|
382 |
+
|
383 |
+
/**
|
384 |
+
* Get package record
|
385 |
+
* @param string $chanName
|
386 |
+
* @param string $packageName
|
387 |
+
* @return array
|
388 |
+
*/
|
389 |
+
protected function fetchPackage($chanName, $packageName, $field = null)
|
390 |
+
{
|
391 |
+
if(null === $field) {
|
392 |
+
return $this->_data[self::K_CHAN][$chanName][self::K_PACK][$packageName];
|
393 |
+
} else {
|
394 |
+
return $this->_data[self::K_CHAN][$chanName][self::K_PACK][$packageName][$field];
|
395 |
+
}
|
396 |
+
}
|
397 |
+
|
398 |
+
/**
|
399 |
+
* Has package record
|
400 |
+
* @param string $chanName
|
401 |
+
* @param string $packageName
|
402 |
+
* @return bool
|
403 |
+
*/
|
404 |
+
protected function hasPackageRecord($chanName, $packageName)
|
405 |
+
{
|
406 |
+
return isset($this->_data[self::K_CHAN][$chanName][self::K_PACK][$packageName]);
|
407 |
+
}
|
408 |
+
|
409 |
+
/**
|
410 |
+
* Get channel name by alias
|
411 |
+
* @param string $alias
|
412 |
+
* @return array
|
413 |
+
*/
|
414 |
+
protected function getChannelNameByAlias($alias)
|
415 |
+
{
|
416 |
+
return $this->_data[self::K_CHAN_ALIAS][$alias];
|
417 |
+
}
|
418 |
+
|
419 |
+
/**
|
420 |
+
* Set channel alias
|
421 |
+
* @param string $alias
|
422 |
+
* @param string $chanName
|
423 |
+
* @return void
|
424 |
+
*/
|
425 |
+
protected function setChannelAlias($alias, $chanName)
|
426 |
+
{
|
427 |
+
$this->_data[self::K_CHAN_ALIAS][$alias] = $chanName;
|
428 |
+
}
|
429 |
+
|
430 |
+
/**
|
431 |
+
* Unset channel alias
|
432 |
+
* @param string $alias
|
433 |
+
* @return void
|
434 |
+
*/
|
435 |
+
protected function unsetChannelAlias($alias)
|
436 |
+
{
|
437 |
+
unset($this->_data[self::K_CHAN_ALIAS][$alias]);
|
438 |
+
}
|
439 |
+
|
440 |
+
/**
|
441 |
+
* Clear all aliases of channel
|
442 |
+
* @param string $chanName channel name
|
443 |
+
* @return void
|
444 |
+
*/
|
445 |
+
protected function clearAliases($chanName)
|
446 |
+
{
|
447 |
+
$keys = array_keys($this->_data[self::K_CHAN_ALIAS]);
|
448 |
+
foreach ($keys as $key) {
|
449 |
+
if($this->_data[self::K_CHAN_ALIAS][$key] == $chanName) {
|
450 |
+
unset($this->_data[self::K_CHAN_ALIAS][$key]);
|
451 |
+
}
|
452 |
+
}
|
453 |
+
}
|
454 |
+
|
455 |
+
/**
|
456 |
+
* Add channel alias
|
457 |
+
* @param string $chanName
|
458 |
+
* @param string $alias
|
459 |
+
* @return void
|
460 |
+
*/
|
461 |
+
public function addChannelAlias($chanName, $alias)
|
462 |
+
{
|
463 |
+
if($this->isChannelName($alias)) {
|
464 |
+
return $this->doError("Alias '{$alias}' is existant channel name!");
|
465 |
+
}
|
466 |
+
|
467 |
+
if(!$this->isChannelName($chanName)) {
|
468 |
+
return $this->doError("Channel '{$chanName}' doesn't exist");
|
469 |
+
}
|
470 |
+
$this->setChannelAlias($alias, $chanName);
|
471 |
+
$this->save();
|
472 |
+
}
|
473 |
+
|
474 |
+
|
475 |
+
|
476 |
+
/**
|
477 |
+
* Add channel
|
478 |
+
* @param $chanName
|
479 |
+
* @param $uri
|
480 |
+
* @param $data
|
481 |
+
* @return void
|
482 |
+
*/
|
483 |
+
public function addChannel($chanName, $uri, $data = array())
|
484 |
+
{
|
485 |
+
if($this->isChannelName($chanName)) {
|
486 |
+
return $this->doError("Channel '{$chanName}' already exist!");
|
487 |
+
}
|
488 |
+
if($this->isChannelUri($uri)) {
|
489 |
+
return $this->doError("Channel with uri= '{$uri}' already exist!");
|
490 |
+
}
|
491 |
+
if($this->isChannelAlias($chanName)) {
|
492 |
+
$this->unsetChannelAlias($chanName);
|
493 |
+
}
|
494 |
+
$uri = $this->formatUri($uri);
|
495 |
+
$this->setChannelRecord($chanName, $uri, $data);
|
496 |
+
$this->setChannelUriRecord($chanName, $uri);
|
497 |
+
$this->save();
|
498 |
+
}
|
499 |
+
|
500 |
+
|
501 |
+
|
502 |
+
/**
|
503 |
+
* Delete channel
|
504 |
+
* @param $chanName
|
505 |
+
* @return void
|
506 |
+
*/
|
507 |
+
public function deleteChannel($chanName)
|
508 |
+
{
|
509 |
+
if($this->isChannelName($chanName)) {
|
510 |
+
$record = $this->getChannelRecord($chanName);
|
511 |
+
$this->unsetChannelUriRecord($record[self::K_URI]);
|
512 |
+
$this->unsetChannelRecord($chanName);
|
513 |
+
$this->clearAliases($chanName);
|
514 |
+
} elseif($this->isChannelUri($chanName)) {
|
515 |
+
$uri = $chanName;
|
516 |
+
$chanName = $this->getChannelUriRecord($uri);
|
517 |
+
$this->unsetChannelUriRecord($uri);
|
518 |
+
$this->unsetChannelRecord($chanName);
|
519 |
+
$this->clearAliases($chanName);
|
520 |
+
} elseif($this->isChannelAlias($chanName)) {
|
521 |
+
$this->unsetChannelAlias($chanName);
|
522 |
+
} else {
|
523 |
+
return $this->doError("'{$chanName}' was not found in aliases, channel names, channel uris");
|
524 |
+
}
|
525 |
+
$this->save();
|
526 |
+
}
|
527 |
+
|
528 |
+
|
529 |
+
/**
|
530 |
+
* Converts channel name, url or alias to channel name
|
531 |
+
* throws exception if not found
|
532 |
+
* @param srting $chanName
|
533 |
+
* @return string
|
534 |
+
*/
|
535 |
+
public function chanName($chanName)
|
536 |
+
{
|
537 |
+
$channelData = $this->getChannel($chanName);
|
538 |
+
if(!$channelData) {
|
539 |
+
return $this->doError("Channel '{$chanName}' doesn't exist");
|
540 |
+
}
|
541 |
+
return $channelData[self::K_NAME];
|
542 |
+
}
|
543 |
+
|
544 |
+
public function chanUrl($chan)
|
545 |
+
{
|
546 |
+
$channelData = $this->getChannel($chan);
|
547 |
+
if(!$channelData) {
|
548 |
+
return $this->doError("Channel '{$chan}' doesn't exist");
|
549 |
+
}
|
550 |
+
return $channelData[self::K_URI];
|
551 |
+
}
|
552 |
+
|
553 |
+
|
554 |
+
/**
|
555 |
+
* Add package
|
556 |
+
* @param Mage_Connect_Package $package
|
557 |
+
* @return void
|
558 |
+
*/
|
559 |
+
public function addPackage($package)
|
560 |
+
{
|
561 |
+
$channel = $this->chanName($package->getChannel());
|
562 |
+
$name = $package->getName();
|
563 |
+
$record = array (
|
564 |
+
self::K_VER => $package->getVersion(),
|
565 |
+
self::K_STATE => $package->getStability(),
|
566 |
+
self::K_XML => $package->getPackageXml(),
|
567 |
+
self::K_NAME => $name,
|
568 |
+
self::K_DEPS => array(),
|
569 |
+
self::K_PACK_DEPS => array(),
|
570 |
+
);
|
571 |
+
$this->setPackageRecord($channel, $name, $record);
|
572 |
+
$this->setPackageDependencies($channel, $name, $package->getDependencyPackages());
|
573 |
+
$this->save();
|
574 |
+
}
|
575 |
+
|
576 |
+
|
577 |
+
|
578 |
+
|
579 |
+
/**
|
580 |
+
* Delete package
|
581 |
+
* @param string $chanName
|
582 |
+
* @param string $package
|
583 |
+
* @return void
|
584 |
+
*/
|
585 |
+
public function deletePackage($chanName, $package)
|
586 |
+
{
|
587 |
+
$chanName = $this->chanName($chanName);
|
588 |
+
$this->unsetPackageRecord($chanName, $package);
|
589 |
+
$this->save();
|
590 |
+
}
|
591 |
+
|
592 |
+
/**
|
593 |
+
* Get package
|
594 |
+
* @param sting $chanName
|
595 |
+
* @param string $package
|
596 |
+
* @return void
|
597 |
+
*/
|
598 |
+
public function getPackage($chanName, $package)
|
599 |
+
{
|
600 |
+
$chanName = $this->chanName($chanName);
|
601 |
+
if($this->hasPackageRecord($chanName, $package)) {
|
602 |
+
return $this->fetchPackage($chanName, $package);
|
603 |
+
}
|
604 |
+
return null;
|
605 |
+
}
|
606 |
+
|
607 |
+
public function getPackageObject($chanName, $package)
|
608 |
+
{
|
609 |
+
$chanName = $this->chanName($chanName);
|
610 |
+
if($this->hasPackageRecord($chanName, $package)) {
|
611 |
+
$data = $this->fetchPackage($chanName, $package);
|
612 |
+
return new Mage_Connect_Package($data[self::K_XML]);
|
613 |
+
}
|
614 |
+
throw new Exception("Cannot get package: '{$package}'");
|
615 |
+
}
|
616 |
+
|
617 |
+
|
618 |
+
public function hasPackage($chanName, $package, $versionMin = false, $versionMax = false)
|
619 |
+
{
|
620 |
+
$chanName = $this->chanName($chanName);
|
621 |
+
$data = $this->getPackage($chanName, $package);
|
622 |
+
if(null === $data) {
|
623 |
+
return false;
|
624 |
+
}
|
625 |
+
$installedVersion = $data[self::K_VER];
|
626 |
+
return $this->versionInRange($installedVersion, $versionMin, $versionMax);
|
627 |
+
}
|
628 |
+
|
629 |
+
public function versionInRange($version, $versionMin = false, $versionMax = false)
|
630 |
+
{
|
631 |
+
if(false === $versionMin) {
|
632 |
+
$minOk = true;
|
633 |
+
} else {
|
634 |
+
$minOk = version_compare($version, $versionMin, ">=");
|
635 |
+
}
|
636 |
+
if(false === $versionMax) {
|
637 |
+
$maxOk = true;
|
638 |
+
} else {
|
639 |
+
$maxOk = version_compare($version, $versionMax, "<=");
|
640 |
+
}
|
641 |
+
return $minOk && $maxOk;
|
642 |
+
}
|
643 |
+
|
644 |
+
public function hasVersionRangeIntersect($min1, $max1, $min2, $max2)
|
645 |
+
{
|
646 |
+
if(version_compare($min1, $min2, ">") && version_compare($max1, $max2, ">")) {
|
647 |
+
return false;
|
648 |
+
} elseif(version_compare($min1, $min2, "<") && version_compare($max1, $max2, "<")) {
|
649 |
+
return false;
|
650 |
+
} elseif(version_compare($min1, $min2, ">=") && version_compare($max1, $max2, "<=")) {
|
651 |
+
return true;
|
652 |
+
} elseif(version_compare($min1, $min2, "<=") && version_compare($max1, $max2, ">=")) {
|
653 |
+
return true;
|
654 |
+
}
|
655 |
+
return false;
|
656 |
+
}
|
657 |
+
|
658 |
+
/**
|
659 |
+
* Clear contents to defaults and save
|
660 |
+
* @return void
|
661 |
+
*/
|
662 |
+
public function clear()
|
663 |
+
{
|
664 |
+
$this->setEmptyConfig();
|
665 |
+
$this->save();
|
666 |
+
}
|
667 |
+
|
668 |
+
/**
|
669 |
+
* Output error - throw exception
|
670 |
+
* @param $message
|
671 |
+
* @throws Exception
|
672 |
+
* @return void
|
673 |
+
*/
|
674 |
+
protected function doError($message)
|
675 |
+
{
|
676 |
+
throw new Exception($message);
|
677 |
+
}
|
678 |
+
|
679 |
+
|
680 |
+
|
681 |
+
|
682 |
+
|
683 |
+
public function compareStabilities($s1, $s2)
|
684 |
+
{
|
685 |
+
if(!$this->_validator) {
|
686 |
+
$this->_validator = new Mage_Connect_Validator();
|
687 |
+
}
|
688 |
+
return $this->_validator->compareStabilities($s1, $s2);
|
689 |
+
}
|
690 |
+
|
691 |
+
|
692 |
+
|
693 |
+
public function detectVersionFromRestArray($restData, $argVersionMin = false, $argVersionMax = false, $preferredStability = 'devel')
|
694 |
+
{
|
695 |
+
|
696 |
+
if(!is_array($restData)) {
|
697 |
+
return false;
|
698 |
+
}
|
699 |
+
|
700 |
+
foreach($restData as $vData) {
|
701 |
+
$stability = trim($vData['s']);
|
702 |
+
$version = trim($vData['v']);
|
703 |
+
$goodStability = $this->compareStabilities($stability, $preferredStability) >= 0;
|
704 |
+
if($goodStability && $this->versionInRange($version, $argVersionMin, $argVersionMax)) {
|
705 |
+
return $version;
|
706 |
+
}
|
707 |
+
}
|
708 |
+
return false;
|
709 |
+
}
|
710 |
+
|
711 |
+
|
712 |
+
public function setPackageDependencies($chanName, $package, $data)
|
713 |
+
{
|
714 |
+
$chanName = $this->chanName($chanName);
|
715 |
+
if($this->hasPackageRecord($chanName, $package)) {
|
716 |
+
$this->setPackageRecord($chanName, $package, $data, self::K_PACK_DEPS);
|
717 |
+
$this->save();
|
718 |
+
return true;
|
719 |
+
}
|
720 |
+
return false;
|
721 |
+
}
|
722 |
+
|
723 |
+
public function getPackageDependencies($chanName, $package)
|
724 |
+
{
|
725 |
+
$chanName = $this->chanName($chanName);
|
726 |
+
if($this->hasPackageRecord($chanName, $package)) {
|
727 |
+
return $this->fetchPackage($chanName, $package, self::K_PACK_DEPS);
|
728 |
+
}
|
729 |
+
return false;
|
730 |
+
}
|
731 |
+
|
732 |
+
|
733 |
+
|
734 |
+
public function setDependencyInfo($chanName, $package, $data)
|
735 |
+
{
|
736 |
+
$chanName = $this->chanName($chanName);
|
737 |
+
if($this->hasPackageRecord($chanName, $package)) {
|
738 |
+
$this->setPackageRecord($chanName, $package, $data, self::K_DEPS);
|
739 |
+
$this->save();
|
740 |
+
return true;
|
741 |
+
}
|
742 |
+
return false;
|
743 |
+
}
|
744 |
+
|
745 |
+
public function getDependencyInfo($chanName, $package)
|
746 |
+
{
|
747 |
+
$chanName = $this->chanName($chanName);
|
748 |
+
if($this->hasPackageRecord($chanName, $package)) {
|
749 |
+
return $this->fetchPackage($chanName, $package, self::K_DEPS);
|
750 |
+
}
|
751 |
+
return false;
|
752 |
+
}
|
753 |
+
|
754 |
+
|
755 |
+
|
756 |
+
public function getChannelNames()
|
757 |
+
{
|
758 |
+
return array_keys($this->_data[self::K_CHAN]);
|
759 |
+
}
|
760 |
+
|
761 |
+
public function getPackagesData($channel = false)
|
762 |
+
{
|
763 |
+
if(false == $channel) {
|
764 |
+
return $this->_data[self::K_CHAN];
|
765 |
+
}
|
766 |
+
|
767 |
+
if(!$this->isChannel($channel)) {
|
768 |
+
return array();
|
769 |
+
}
|
770 |
+
return $this->getChannel($channel);
|
771 |
+
}
|
772 |
+
|
773 |
+
public function specifiedInDependencyList($deps, $chanName, $packageName)
|
774 |
+
{
|
775 |
+
foreach($deps as $dep) {
|
776 |
+
if($chanName == $dep['channel'] && $packageName == $dep['name']) {
|
777 |
+
return true;
|
778 |
+
}
|
779 |
+
}
|
780 |
+
return false;
|
781 |
+
}
|
782 |
+
|
783 |
+
public function requiredByOtherPackages($chanName, $packageName, $excludeList = array())
|
784 |
+
{
|
785 |
+
$out = array();
|
786 |
+
foreach($this->_data[self::K_CHAN] as $channel=>$data) {
|
787 |
+
foreach($data[self::K_PACK] as $package) {
|
788 |
+
if($this->specifiedInDependencyList($excludeList, $channel, $package['name'])) {
|
789 |
+
continue;
|
790 |
+
}
|
791 |
+
$deps = $package[self::K_PACK_DEPS];
|
792 |
+
if($this->specifiedInDependencyList($deps, $chanName, $packageName)) {
|
793 |
+
$out[] = array('channel'=>$channel, 'name' =>$package['name'], 'version'=>$package['version']);
|
794 |
+
}
|
795 |
+
}
|
796 |
+
}
|
797 |
+
return $out;
|
798 |
+
}
|
799 |
+
|
800 |
+
|
801 |
+
|
802 |
+
|
803 |
+
public function getInstalledPackages($chanName = false)
|
804 |
+
{
|
805 |
+
if(false == $chanName) {
|
806 |
+
$data = $this->getChannelNames();
|
807 |
+
} elseif($this->isChannel($chanName)) {
|
808 |
+
$tmp = $this->getChannel($chanName);
|
809 |
+
$data = array($tmp[self::K_NAME]);
|
810 |
+
}
|
811 |
+
$out = array();
|
812 |
+
foreach( $data as $chanName) {
|
813 |
+
$channel = $this->getChannel($chanName);
|
814 |
+
$out[$chanName] = array();
|
815 |
+
foreach($channel[self::K_PACK] as $package=>$data) {
|
816 |
+
$out[$chanName][$package] = array();
|
817 |
+
foreach(array(self::K_VER, self::K_STATE) as $k) {
|
818 |
+
$out[$chanName][$package][$k] = $data[$k];
|
819 |
+
}
|
820 |
+
}
|
821 |
+
}
|
822 |
+
return $out;
|
823 |
+
}
|
824 |
+
|
825 |
+
|
826 |
+
|
827 |
+
/**
|
828 |
+
* Check if package conflicts with installed packages
|
829 |
+
* Returns:
|
830 |
+
* array with conflicts
|
831 |
+
* false if no conflicts
|
832 |
+
*
|
833 |
+
* @param string $chanName
|
834 |
+
* @param string $packageName
|
835 |
+
* @param string $version
|
836 |
+
* @return array|false
|
837 |
+
*/
|
838 |
+
public function hasConflicts($chanName, $packageName, $version)
|
839 |
+
{
|
840 |
+
$conflicts = array();
|
841 |
+
foreach($this->_data[self::K_CHAN] as $channel=>$data) {
|
842 |
+
foreach($data[self::K_PACK] as $package) {
|
843 |
+
if($channel != $chanName) {
|
844 |
+
continue;
|
845 |
+
}
|
846 |
+
$deps = $package[self::K_PACK_DEPS];
|
847 |
+
foreach($deps as $dep) {
|
848 |
+
if($dep['name'] != $packageName) {
|
849 |
+
continue;
|
850 |
+
}
|
851 |
+
|
852 |
+
if(!$this->versionInRange($version, $dep['min'], $dep['max'])) {
|
853 |
+
//var_dump($version, $dep['min'], $dep['max']);
|
854 |
+
$conflicts[] = $channel . "/". $package['name'] ." ". $package['version'];
|
855 |
+
}
|
856 |
+
}
|
857 |
+
}
|
858 |
+
}
|
859 |
+
return count($conflicts) ? $conflicts : false;
|
860 |
+
}
|
861 |
+
|
862 |
+
|
863 |
+
|
864 |
+
|
865 |
+
}
|
lib/Mage/Connect/Structures/Graph.php
ADDED
@@ -0,0 +1,248 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
class Mage_Connect_Structures_Graph
|
28 |
+
{
|
29 |
+
protected $_nodes = array();
|
30 |
+
protected $_directed = false;
|
31 |
+
protected $_nodeClassName = 'Mage_Connect_Structures_Node';
|
32 |
+
|
33 |
+
const ACYCLIC_VISITED_KEY = 'acyclic-test-visited';
|
34 |
+
const SORT_VISITED_KEY = 'topological-sort-visited';
|
35 |
+
const SORT_LEVEL_KEY = 'topological-sort-level';
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Constructor
|
39 |
+
* @param bool $directed directed graph?
|
40 |
+
* @return void
|
41 |
+
*/
|
42 |
+
public function __construct($directed = true)
|
43 |
+
{
|
44 |
+
$this->_directed = $directed;
|
45 |
+
}
|
46 |
+
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Is graph directed?
|
50 |
+
*
|
51 |
+
* @return bool
|
52 |
+
*/
|
53 |
+
public function isDirected()
|
54 |
+
{
|
55 |
+
return (boolean) $this->_directed;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Add node to list
|
60 |
+
*
|
61 |
+
* @param Mage_Connect_Structures_Graph_Node $newNode
|
62 |
+
* @return void
|
63 |
+
*/
|
64 |
+
public function addNode(&$newNode)
|
65 |
+
{
|
66 |
+
if(!$newNode instanceof $this->_nodeClassName) {
|
67 |
+
throw new Exception(__METHOD__." : invalid node class, should be instance of: ".$this->_nodeClassName);
|
68 |
+
}
|
69 |
+
foreach($this->_nodes as $key => $node) {
|
70 |
+
if($newNode === $node) {
|
71 |
+
throw new Exception(__METHOD__." : received duplicate object");
|
72 |
+
}
|
73 |
+
}
|
74 |
+
$this->_nodes[] =& $newNode;
|
75 |
+
$newNode->setGraph($this);
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Remove a Node from the Graph
|
80 |
+
* @param Mage_Connect_Structures_Graph_Node $node
|
81 |
+
*/
|
82 |
+
public function removeNode(&$node)
|
83 |
+
{
|
84 |
+
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Return set of nodes
|
89 |
+
* @return array
|
90 |
+
*/
|
91 |
+
public function &getNodes()
|
92 |
+
{
|
93 |
+
return $this->_nodes;
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Is asyclic
|
98 |
+
* @return unknown_type
|
99 |
+
*/
|
100 |
+
public function isAcyclic()
|
101 |
+
{
|
102 |
+
if (!$this->isDirected()) {
|
103 |
+
return false;
|
104 |
+
}
|
105 |
+
return self::_isAcyclic($this);
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
*
|
110 |
+
* This is a variant of Graph::inDegree which does
|
111 |
+
* not count nodes marked as visited.
|
112 |
+
*
|
113 |
+
* @return integer
|
114 |
+
*/
|
115 |
+
protected static function _nonVisitedInDegree(&$node, $metadataKey)
|
116 |
+
{
|
117 |
+
$result = 0;
|
118 |
+
$graphNodes =& $node->getGraph()->getNodes();
|
119 |
+
foreach (array_keys($graphNodes) as $key) {
|
120 |
+
if ((!$graphNodes[$key]->getMetadata($metadataKey)) && $graphNodes[$key]->connectsTo($node)) {
|
121 |
+
$result++;
|
122 |
+
}
|
123 |
+
}
|
124 |
+
return $result;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Is graph acyclic?
|
129 |
+
* @param $graph
|
130 |
+
* @return bool
|
131 |
+
*/
|
132 |
+
protected static function _isAcyclic(&$graph)
|
133 |
+
{
|
134 |
+
// Mark every node as not visited
|
135 |
+
$nodes =& $graph->getNodes();
|
136 |
+
$nodeKeys = array_keys($nodes);
|
137 |
+
$refGenerator = array();
|
138 |
+
foreach($nodeKeys as $key) {
|
139 |
+
$refGenerator[] = false;
|
140 |
+
$nodes[$key]->setMetadata(self::ACYCLIC_VISITED_KEY, $refGenerator[sizeof($refGenerator) - 1]);
|
141 |
+
}
|
142 |
+
|
143 |
+
// Iteratively peel off leaf nodes
|
144 |
+
do {
|
145 |
+
// Find out which nodes are leafs (excluding visited nodes)
|
146 |
+
$leafNodes = array();
|
147 |
+
foreach($nodeKeys as $key) {
|
148 |
+
if ((!$nodes[$key]->getMetadata(self::ACYCLIC_VISITED_KEY)) &&
|
149 |
+
self::_nonVisitedInDegree($nodes[$key], self::ACYCLIC_VISITED_KEY) == 0) {
|
150 |
+
$leafNodes[] =& $nodes[$key];
|
151 |
+
}
|
152 |
+
}
|
153 |
+
// Mark leafs as visited
|
154 |
+
for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) {
|
155 |
+
$visited =& $leafNodes[$i]->getMetadata(self::ACYCLIC_VISITED_KEY);
|
156 |
+
$visited = true;
|
157 |
+
$leafNodes[$i]->setMetadata(self::ACYCLIC_VISITED_KEY, $visited);
|
158 |
+
}
|
159 |
+
} while (sizeof($leafNodes) > 0);
|
160 |
+
|
161 |
+
|
162 |
+
// If graph is a DAG, there should be no non-visited nodes.
|
163 |
+
// Let's try to prove otherwise
|
164 |
+
$result = true;
|
165 |
+
foreach($nodeKeys as $key) {
|
166 |
+
if (!$nodes[$key]->getMetadata(self::ACYCLIC_VISITED_KEY)) {
|
167 |
+
$result = false;
|
168 |
+
break;
|
169 |
+
}
|
170 |
+
}
|
171 |
+
|
172 |
+
// Cleanup visited marks
|
173 |
+
foreach($nodeKeys as $key) {
|
174 |
+
$nodes[$key]->unsetMetadata(self::ACYCLIC_VISITED_KEY);
|
175 |
+
}
|
176 |
+
|
177 |
+
return $result;
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
*
|
182 |
+
* sort returns the graph's nodes, sorted by topological order.
|
183 |
+
*
|
184 |
+
* The result is an array with
|
185 |
+
* as many entries as topological levels.
|
186 |
+
*
|
187 |
+
* Each entry in this array is an array of nodes within
|
188 |
+
* the given topological level.
|
189 |
+
*
|
190 |
+
* @return array
|
191 |
+
*/
|
192 |
+
public function topologicalSort()
|
193 |
+
{
|
194 |
+
// We only sort graphs
|
195 |
+
self::_topologicalSort($this);
|
196 |
+
$result = array();
|
197 |
+
// Fill out result array
|
198 |
+
$nodes =& $this->getNodes();
|
199 |
+
$nodeKeys = array_keys($nodes);
|
200 |
+
foreach($nodeKeys as $key) {
|
201 |
+
$k = $nodes[$key]->getMetadata(self::SORT_LEVEL_KEY);
|
202 |
+
if (!array_key_exists($k, $result)) {
|
203 |
+
$result[$k] = array();
|
204 |
+
}
|
205 |
+
$result[$k][] =& $nodes[$key];
|
206 |
+
$nodes[$key]->unsetMetadata(self::SORT_LEVEL_KEY);
|
207 |
+
}
|
208 |
+
return $result;
|
209 |
+
}
|
210 |
+
|
211 |
+
protected static function _topologicalSort(&$graph)
|
212 |
+
{
|
213 |
+
// Mark every node as not visited
|
214 |
+
$nodes =& $graph->getNodes();
|
215 |
+
$nodeKeys = array_keys($nodes);
|
216 |
+
$refGenerator = array();
|
217 |
+
foreach($nodeKeys as $key) {
|
218 |
+
$refGenerator[] = false;
|
219 |
+
$nodes[$key]->setMetadata(self::SORT_VISITED_KEY, $refGenerator[sizeof($refGenerator) - 1]);
|
220 |
+
}
|
221 |
+
|
222 |
+
// Iteratively peel off leaf nodes
|
223 |
+
$topologicalLevel = 0;
|
224 |
+
do {
|
225 |
+
// Find out which nodes are leafs (excluding visited nodes)
|
226 |
+
$leafNodes = array();
|
227 |
+
foreach($nodeKeys as $key) {
|
228 |
+
if ((!$nodes[$key]->getMetadata(self::SORT_VISITED_KEY)) && self::_nonVisitedInDegree($nodes[$key], self::SORT_VISITED_KEY) == 0) {
|
229 |
+
$leafNodes[] =& $nodes[$key];
|
230 |
+
}
|
231 |
+
}
|
232 |
+
// Mark leafs as visited
|
233 |
+
$refGenerator[] = $topologicalLevel;
|
234 |
+
for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) {
|
235 |
+
$visited =& $leafNodes[$i]->getMetadata(self::SORT_VISITED_KEY);
|
236 |
+
$visited = true;
|
237 |
+
$leafNodes[$i]->setMetadata(self::SORT_VISITED_KEY, $visited);
|
238 |
+
$leafNodes[$i]->setMetadata(self::SORT_LEVEL_KEY, $refGenerator[sizeof($refGenerator) - 1]);
|
239 |
+
}
|
240 |
+
$topologicalLevel++;
|
241 |
+
} while (sizeof($leafNodes) > 0);
|
242 |
+
|
243 |
+
foreach($nodeKeys as $key) {
|
244 |
+
$nodes[$key]->unsetMetadata(self::SORT_VISITED_KEY);
|
245 |
+
}
|
246 |
+
}
|
247 |
+
|
248 |
+
}
|
lib/Mage/Connect/Structures/Node.php
ADDED
@@ -0,0 +1,257 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
class Mage_Connect_Structures_Node
|
28 |
+
{
|
29 |
+
|
30 |
+
protected $_data = null;
|
31 |
+
protected $_metadata = array();
|
32 |
+
protected $_arcs = array();
|
33 |
+
protected $_graph = null;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Node graph getter
|
37 |
+
*
|
38 |
+
* @return Mage_Connect_Structures_Graph
|
39 |
+
*/
|
40 |
+
public function &getGraph()
|
41 |
+
{
|
42 |
+
return $this->_graph;
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
*
|
47 |
+
* Node graph setter.
|
48 |
+
* This method should not be called directly.
|
49 |
+
* Use Graph::addNode instead.
|
50 |
+
*
|
51 |
+
* @param $graph
|
52 |
+
*/
|
53 |
+
public function setGraph(&$graph)
|
54 |
+
{
|
55 |
+
$this->_graph =& $graph;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
*
|
60 |
+
* Node data getter.
|
61 |
+
*
|
62 |
+
* Each graph node can contain a reference to one variable. This is the getter for that reference.
|
63 |
+
*
|
64 |
+
* @return mixed Data stored in node
|
65 |
+
* @access public
|
66 |
+
*/
|
67 |
+
public function &getData()
|
68 |
+
{
|
69 |
+
return $this->_data;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Node data setter
|
74 |
+
*
|
75 |
+
* Each graph node can contain a reference to one variable. This is the setter for that reference.
|
76 |
+
*
|
77 |
+
* @return mixed Data to store in node
|
78 |
+
*/
|
79 |
+
public function setData($data)
|
80 |
+
{
|
81 |
+
$this->_data =& $data;
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
*
|
86 |
+
* Test for existence of metadata under a given key.
|
87 |
+
*
|
88 |
+
* @param string Key to test
|
89 |
+
* @return boolean
|
90 |
+
* @access public
|
91 |
+
*/
|
92 |
+
public function metadataKeyExists($key)
|
93 |
+
{
|
94 |
+
return array_key_exists($key, $this->_metadata);
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
*
|
99 |
+
* Get node metadata
|
100 |
+
*
|
101 |
+
* @param string $key
|
102 |
+
* @param boolean $nullIfNonexistent (defaults to false).
|
103 |
+
* @return mixed
|
104 |
+
*/
|
105 |
+
public function & getMetadata($key, $nullIfNonexistent = false)
|
106 |
+
{
|
107 |
+
if (array_key_exists($key, $this->_metadata)) {
|
108 |
+
return $this->_metadata[$key];
|
109 |
+
} elseif ($nullIfNonexistent) {
|
110 |
+
$a = null;
|
111 |
+
return $a;
|
112 |
+
} else {
|
113 |
+
throw new Exception(__METHOD__." : requested key doesn't exist: {$key}");
|
114 |
+
}
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
*
|
119 |
+
* Delete metadata by key
|
120 |
+
*
|
121 |
+
* @param string Key
|
122 |
+
*/
|
123 |
+
public function unsetMetadata($key)
|
124 |
+
{
|
125 |
+
if (array_key_exists($key, $this->_metadata)) {
|
126 |
+
unset($this->_metadata[$key]);
|
127 |
+
}
|
128 |
+
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
*
|
133 |
+
* Node metadata setter
|
134 |
+
*
|
135 |
+
* Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an
|
136 |
+
* associative array or in a dictionary. This method stores data under the given key. If the key already exists,
|
137 |
+
* previously stored data is discarded.
|
138 |
+
*
|
139 |
+
* @param string $key
|
140 |
+
* @param mixed $data
|
141 |
+
*/
|
142 |
+
public function setMetadata($key, $data)
|
143 |
+
{
|
144 |
+
$this->_metadata[$key] =& $data;
|
145 |
+
}
|
146 |
+
|
147 |
+
protected function _connectTo(&$destinationNode)
|
148 |
+
{
|
149 |
+
$this->_arcs[] =& $destinationNode;
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Connect this node to another one.
|
154 |
+
* If the graph is not directed, the reverse arc, connecting $destinationNode to $this is also created.
|
155 |
+
* @param Structures_Graph Node to connect to
|
156 |
+
*/
|
157 |
+
public function connectTo(&$destinationNode)
|
158 |
+
{
|
159 |
+
$class = get_class($this);
|
160 |
+
if(!$destinationNode instanceof $class) {
|
161 |
+
throw new Exception(__METHOD__." : argument should be instance of {$class}");
|
162 |
+
}
|
163 |
+
|
164 |
+
// Nodes must already be in graphs to be connected
|
165 |
+
if ($this->_graph == null) {
|
166 |
+
throw new Exception(__METHOD__." : tried to connect to null graph");
|
167 |
+
}
|
168 |
+
|
169 |
+
if ($destinationNode->getGraph() == null) {
|
170 |
+
throw new Exception(__METHOD__." : tried to connect to node that is not connected to any graph");
|
171 |
+
}
|
172 |
+
|
173 |
+
// Connect here
|
174 |
+
$this->_connectTo($destinationNode);
|
175 |
+
// If graph is undirected, connect back
|
176 |
+
if (!$this->_graph->isDirected()) {
|
177 |
+
$destinationNode->_connectTo($this);
|
178 |
+
}
|
179 |
+
}
|
180 |
+
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Return nodes connected to this one.
|
184 |
+
* @return array
|
185 |
+
*/
|
186 |
+
public function getNeighbours()
|
187 |
+
{
|
188 |
+
return $this->_arcs;
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Test wether this node has an arc to the target node
|
193 |
+
* Returns true if the two nodes are connected
|
194 |
+
* @return boolean
|
195 |
+
*/
|
196 |
+
public function connectsTo(&$target)
|
197 |
+
{
|
198 |
+
$arcKeys = array_keys($this->_arcs);
|
199 |
+
foreach($arcKeys as $key) {
|
200 |
+
$arc =& $this->_arcs[$key];
|
201 |
+
if ($target === $arc) {
|
202 |
+
return true;
|
203 |
+
}
|
204 |
+
}
|
205 |
+
return false;
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Calculate the in degree of the node.
|
210 |
+
*
|
211 |
+
* The indegree for a node is the number of arcs
|
212 |
+
* entering the node.
|
213 |
+
*
|
214 |
+
* For non directed graphs:
|
215 |
+
* always outdegree = indegree.
|
216 |
+
*
|
217 |
+
* @return int
|
218 |
+
*/
|
219 |
+
public function inDegree()
|
220 |
+
{
|
221 |
+
$result = 0;
|
222 |
+
|
223 |
+
if ($this->_graph == null) {
|
224 |
+
return $result;
|
225 |
+
}
|
226 |
+
if (!$this->_graph->isDirected()) {
|
227 |
+
return $this->outDegree();
|
228 |
+
}
|
229 |
+
|
230 |
+
$graphNodes =& $this->_graph->getNodes();
|
231 |
+
foreach (array_keys($graphNodes) as $key) {
|
232 |
+
if ($graphNodes[$key]->connectsTo($this)) {
|
233 |
+
$result++;
|
234 |
+
}
|
235 |
+
}
|
236 |
+
return $result;
|
237 |
+
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Calculate the out degree of the node.
|
242 |
+
*
|
243 |
+
* The outdegree for a node is the number of arcs exiting the node.
|
244 |
+
* For non directed graphs:
|
245 |
+
* always outdegree = indegree.
|
246 |
+
*
|
247 |
+
* @return int
|
248 |
+
*/
|
249 |
+
public function outDegree()
|
250 |
+
{
|
251 |
+
if ($this->_graph == null) {
|
252 |
+
return 0;
|
253 |
+
}
|
254 |
+
return count($this->_arcs);
|
255 |
+
}
|
256 |
+
|
257 |
+
}
|
lib/Mage/Connect/Validator.php
ADDED
@@ -0,0 +1,417 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to validate string resources
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
|
35 |
+
class Mage_Connect_Validator
|
36 |
+
{
|
37 |
+
protected static $_stability = array(0=>'devel',1=>'alpha',2=>'beta',3=>'stable');
|
38 |
+
|
39 |
+
|
40 |
+
public static function getStabilities()
|
41 |
+
{
|
42 |
+
return self::$_stability;
|
43 |
+
}
|
44 |
+
|
45 |
+
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Compare stabilities. Returns:
|
49 |
+
*
|
50 |
+
* -1 if the first stability is lower than the second
|
51 |
+
* 0 if they are equal
|
52 |
+
* 1 if the second is lower.
|
53 |
+
* @param $s1
|
54 |
+
* @param $s2
|
55 |
+
* @return int
|
56 |
+
*/
|
57 |
+
public function compareStabilities($s1, $s2)
|
58 |
+
{
|
59 |
+
$list = $this->getStabilities();
|
60 |
+
$tmp = array_combine(array_values($list),array_keys($list));
|
61 |
+
|
62 |
+
if(!isset($tmp[$s1], $tmp[$s2])) {
|
63 |
+
throw new Exception("Invalid stability in compareStabilities argument");
|
64 |
+
}
|
65 |
+
|
66 |
+
|
67 |
+
// 'stable' turns to 3
|
68 |
+
// 'devel' turns to 0
|
69 |
+
$s1 = $tmp[$s1];
|
70 |
+
$s2 = $tmp[$s2];
|
71 |
+
if($s1 === $s2) {
|
72 |
+
return 0;
|
73 |
+
} elseif($s1 > $s2) {
|
74 |
+
return 1;
|
75 |
+
} elseif($s1 < $s2) {
|
76 |
+
return -1;
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Constructor
|
82 |
+
*/
|
83 |
+
public function __construct()
|
84 |
+
{
|
85 |
+
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Validate max len of string
|
90 |
+
* @param string $str
|
91 |
+
* @param int $maxLen
|
92 |
+
* @return bool
|
93 |
+
*/
|
94 |
+
public function validateMaxLen($str, $maxLen)
|
95 |
+
{
|
96 |
+
return strlen((string) $str) <= (int) $maxLen;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Validate channel name and url
|
101 |
+
*
|
102 |
+
* @param mixed $str
|
103 |
+
* @return bool
|
104 |
+
*/
|
105 |
+
public function validateChannelNameOrUri($str)
|
106 |
+
{
|
107 |
+
return ( $this->validateUrl($str) || $this->validatePackageName($str));
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Validate License url
|
112 |
+
*
|
113 |
+
* @param mixed $str
|
114 |
+
* @return boolean
|
115 |
+
*/
|
116 |
+
public function validateLicenseUrl($str)
|
117 |
+
{
|
118 |
+
if ($str) {
|
119 |
+
return ( $this->validateUrl($str) || $this->validatePackageName($str));
|
120 |
+
}
|
121 |
+
return true;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Validate compatible data
|
126 |
+
* @param array $data
|
127 |
+
* @return bool
|
128 |
+
*/
|
129 |
+
public function validateCompatible(array $data)
|
130 |
+
{
|
131 |
+
if(!count($data)) {
|
132 |
+
/**
|
133 |
+
* Allow empty
|
134 |
+
*/
|
135 |
+
return true;
|
136 |
+
}
|
137 |
+
$count = 0;
|
138 |
+
foreach($data as $k=>$v) {
|
139 |
+
foreach(array('name','channel','min','max') as $fld) {
|
140 |
+
$$fld = trim($v[$fld]);
|
141 |
+
}
|
142 |
+
$count++;
|
143 |
+
|
144 |
+
$res = $this->validateUrl($channel) && strlen($channel);
|
145 |
+
if(!$res) {
|
146 |
+
$this->addError("Invalid or empty channel in compat. #{$count}");
|
147 |
+
}
|
148 |
+
|
149 |
+
$res = $this->validatePackageName($name) && strlen($name);
|
150 |
+
if(!$res) {
|
151 |
+
$this->addError("Invalid or empty name in compat. #{$count}");
|
152 |
+
}
|
153 |
+
$res1 = $this->validateVersion($min);
|
154 |
+
if(!$res1) {
|
155 |
+
$this->addError("Invalid or empty minVersion in compat. #{$count}");
|
156 |
+
}
|
157 |
+
$res2 = $this->validateVersion($max);
|
158 |
+
if(!$res2) {
|
159 |
+
$this->addError("Invalid or empty maxVersion in compat. #{$count}");
|
160 |
+
}
|
161 |
+
if($res1 && $res2 && $this->versionLower($max, $min)) {
|
162 |
+
$this->addError("Max version is lower than min in compat #{$count}");
|
163 |
+
}
|
164 |
+
|
165 |
+
}
|
166 |
+
return ! $this->hasErrors();
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Validate authors of package
|
171 |
+
* @param array $authors
|
172 |
+
* @return bool
|
173 |
+
*/
|
174 |
+
public function validateAuthors(array $authors)
|
175 |
+
{
|
176 |
+
if(!count($authors)) {
|
177 |
+
$this->addError('Empty authors section');
|
178 |
+
return false;
|
179 |
+
}
|
180 |
+
$count = 0;
|
181 |
+
foreach($authors as $k=>$v) {
|
182 |
+
$count++;
|
183 |
+
array_map('trim', $v);
|
184 |
+
$name = $v['name'];
|
185 |
+
$login = $v['user'];
|
186 |
+
$email = $v['email'];
|
187 |
+
$res = $this->validateMaxLen($name, 256) && strlen($name);
|
188 |
+
if(!$res) {
|
189 |
+
$this->addError("Invalid or empty name for author #{$count}");
|
190 |
+
}
|
191 |
+
$res = $this->validatePackageName($login) && strlen($login);
|
192 |
+
if(!$res) {
|
193 |
+
$this->addError("Invalid or empty login for author #{$count}");
|
194 |
+
}
|
195 |
+
$res = $this->validateEmail($email);
|
196 |
+
if(!$res) {
|
197 |
+
$this->addError("Invalid or empty email for author #{$count}");
|
198 |
+
}
|
199 |
+
}
|
200 |
+
return ! $this->hasErrors();
|
201 |
+
}
|
202 |
+
|
203 |
+
|
204 |
+
/**
|
205 |
+
* Validator errors
|
206 |
+
* @var array
|
207 |
+
*/
|
208 |
+
private $_errors = array();
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Add error
|
212 |
+
* @param string $err
|
213 |
+
* @return
|
214 |
+
*/
|
215 |
+
private function addError($err)
|
216 |
+
{
|
217 |
+
$this->_errors[] = $err;
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Set validator errors
|
222 |
+
* @param array $err
|
223 |
+
* @return
|
224 |
+
*/
|
225 |
+
|
226 |
+
private function setErrors(array $err)
|
227 |
+
{
|
228 |
+
$this->_errors = $err;
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Clear validator errors
|
233 |
+
* @return
|
234 |
+
*/
|
235 |
+
private function clearErrors()
|
236 |
+
{
|
237 |
+
$this->_errors = array();
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Check if there are validator errors set
|
242 |
+
* @return unknown_type
|
243 |
+
*/
|
244 |
+
public function hasErrors()
|
245 |
+
{
|
246 |
+
return count($this->_errors) != 0;
|
247 |
+
}
|
248 |
+
|
249 |
+
|
250 |
+
/**
|
251 |
+
* Get errors
|
252 |
+
* @param bool $clear if true after this call erros will be cleared
|
253 |
+
* @return array
|
254 |
+
*/
|
255 |
+
public function getErrors($clear = true)
|
256 |
+
{
|
257 |
+
$out = $this->_errors;
|
258 |
+
if($clear) {
|
259 |
+
$this->clearErrors();
|
260 |
+
}
|
261 |
+
return $out;
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* Validate URL
|
266 |
+
* @param string $str
|
267 |
+
* @return bool
|
268 |
+
*/
|
269 |
+
public function validateUrl($str)
|
270 |
+
{
|
271 |
+
$regex = "@([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}|"
|
272 |
+
."(((news|telnet|nttp|file|http|ftp|https)://)|(www|ftp)"
|
273 |
+
."[-A-Za-z0-9]*\\.)[-A-Za-z0-9\\.]+)(:[0-9]*)?@i";
|
274 |
+
return preg_match($regex, $str);
|
275 |
+
}
|
276 |
+
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Validates package stability
|
280 |
+
* @param string $str
|
281 |
+
* @return bool
|
282 |
+
*/
|
283 |
+
public function validateStability($str)
|
284 |
+
{
|
285 |
+
return in_array(strval($str), self::$_stability);
|
286 |
+
}
|
287 |
+
|
288 |
+
/**
|
289 |
+
* Validate date format
|
290 |
+
* @param $date
|
291 |
+
* @return bool
|
292 |
+
*/
|
293 |
+
public function validateDate($date)
|
294 |
+
{
|
295 |
+
$subs = null;
|
296 |
+
$check1 = preg_match("/^([\d]{4})-([\d]{2})-([\d]{2})$/i", $date, $subs);
|
297 |
+
if(!$check1) {
|
298 |
+
return false;
|
299 |
+
}
|
300 |
+
return checkdate($subs[2], $subs[3], $subs[1]);
|
301 |
+
}
|
302 |
+
|
303 |
+
|
304 |
+
/**
|
305 |
+
* Validate email
|
306 |
+
* @param string $email
|
307 |
+
* @return bool
|
308 |
+
*/
|
309 |
+
public function validateEmail($email)
|
310 |
+
{
|
311 |
+
return preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $email);
|
312 |
+
}
|
313 |
+
|
314 |
+
/**
|
315 |
+
* Validate package name
|
316 |
+
* @param $name
|
317 |
+
* @return bool
|
318 |
+
*/
|
319 |
+
public function validatePackageName($name)
|
320 |
+
{
|
321 |
+
return preg_match("/^[a-zA-Z0-9_-]+$/i", $name);
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* Validate version number
|
326 |
+
* @param string $version
|
327 |
+
* @return bool
|
328 |
+
*/
|
329 |
+
public function validateVersion($version)
|
330 |
+
{
|
331 |
+
return preg_match("/^[\d]+\.[\d]+\.[\d]+([[:alnum:]\.\-\_]+)?$/i", $version);
|
332 |
+
}
|
333 |
+
|
334 |
+
/**
|
335 |
+
* Check versions are equal
|
336 |
+
* @param string $v1
|
337 |
+
* @param string $v2
|
338 |
+
* @return bool
|
339 |
+
*/
|
340 |
+
public function versionEqual($v1, $v2)
|
341 |
+
{
|
342 |
+
return version_compare($v1, $v2, "==");
|
343 |
+
}
|
344 |
+
|
345 |
+
/**
|
346 |
+
* Check version $v1 <= $v2
|
347 |
+
* @param string $v1
|
348 |
+
* @param string $v2
|
349 |
+
* @return bool
|
350 |
+
*/
|
351 |
+
public function versionLowerEqual($v1, $v2)
|
352 |
+
{
|
353 |
+
return version_compare($v1, $v2, "le");
|
354 |
+
}
|
355 |
+
|
356 |
+
|
357 |
+
/**
|
358 |
+
* Check if version $v1 lower than $v2
|
359 |
+
* @param string $v1
|
360 |
+
* @param string $v2
|
361 |
+
* @return bool
|
362 |
+
*/
|
363 |
+
public function versionLower($v1, $v2)
|
364 |
+
{
|
365 |
+
return version_compare($v1, $v2, "<");
|
366 |
+
}
|
367 |
+
|
368 |
+
/**
|
369 |
+
* Check version $v1 >= $v2
|
370 |
+
* @param string $v1
|
371 |
+
* @param string $v2
|
372 |
+
* @return bool
|
373 |
+
*/
|
374 |
+
public function versionGreaterEqual($v1, $v2)
|
375 |
+
{
|
376 |
+
return version_compare($v1, $v2, "ge");
|
377 |
+
}
|
378 |
+
|
379 |
+
|
380 |
+
/**
|
381 |
+
* Generic regex validation
|
382 |
+
* @param string $str
|
383 |
+
* @param string $regex
|
384 |
+
* @return bool
|
385 |
+
*/
|
386 |
+
public function validateRegex($str, $regex)
|
387 |
+
{
|
388 |
+
return preg_match($regex, $str);
|
389 |
+
}
|
390 |
+
|
391 |
+
|
392 |
+
/**
|
393 |
+
* Check if PHP extension loaded
|
394 |
+
* @param string $name Extension name
|
395 |
+
* @return bool
|
396 |
+
*/
|
397 |
+
public function validatePhpExtension($name)
|
398 |
+
{
|
399 |
+
return extension_loaded($name);
|
400 |
+
}
|
401 |
+
|
402 |
+
|
403 |
+
public function validatePHPVersion($min, $max, $ver = PHP_VERSION)
|
404 |
+
{
|
405 |
+
$minAccepted = true;
|
406 |
+
if($min) {
|
407 |
+
$minAccepted = version_compare($ver, $min, ">=");
|
408 |
+
}
|
409 |
+
$maxAccepted = true;
|
410 |
+
if($max) {
|
411 |
+
$maxAccepted = version_compate($ver, $max, "<=");
|
412 |
+
}
|
413 |
+
return (bool) $minAccepted && $maxAccepted;
|
414 |
+
}
|
415 |
+
|
416 |
+
|
417 |
+
}
|
lib/Mage/DB/Exception.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Db
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* TODO
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Db
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_DB_Exception extends Exception {
|
35 |
+
|
36 |
+
}
|
lib/Mage/DB/Mysqli.php
ADDED
@@ -0,0 +1,532 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Db
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Mysqli database connector
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Db
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_DB_Mysqli
|
35 |
+
{
|
36 |
+
/**
|
37 |
+
* Default port
|
38 |
+
* @var int
|
39 |
+
*/
|
40 |
+
const DEFAULT_PORT = 3306;
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Table name escaper
|
44 |
+
* @var string
|
45 |
+
*/
|
46 |
+
const TABLE_ESCAPER = '`';
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Value escaper
|
50 |
+
* @var unknown_type
|
51 |
+
*/
|
52 |
+
const VALUE_ESCAPER = '"';
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Connection
|
56 |
+
* @var mysqli
|
57 |
+
*/
|
58 |
+
protected $conn;
|
59 |
+
/**
|
60 |
+
* Fetch mode
|
61 |
+
* @var unknown_type
|
62 |
+
*/
|
63 |
+
private $fetch_mode = MYSQLI_ASSOC;
|
64 |
+
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Constructor
|
68 |
+
*/
|
69 |
+
public function __construct()
|
70 |
+
{
|
71 |
+
$this->conn = new mysqli();
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Connect
|
76 |
+
* @param string $host
|
77 |
+
* @param string $user
|
78 |
+
* @param string $paswd
|
79 |
+
* @param string $db
|
80 |
+
* @param int $port
|
81 |
+
* @return mixed
|
82 |
+
*/
|
83 |
+
public function connect($host, $user, $paswd, $db, $port = self::DEFAULT_PORT)
|
84 |
+
{
|
85 |
+
$port = (int) $port;
|
86 |
+
$res = @$this->conn->connect($host, $user, $paswd, $db, $port);
|
87 |
+
if(0 !== mysqli_connect_errno($this->conn)) {
|
88 |
+
throw new Mage_DB_Exception(mysqli_connect_error($this->conn));
|
89 |
+
}
|
90 |
+
return $res;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Select database
|
95 |
+
* @param $db db name
|
96 |
+
* @return mixed
|
97 |
+
*/
|
98 |
+
public function selectDb($db)
|
99 |
+
{
|
100 |
+
$res = mysqli_select_db($this->conn, $db);
|
101 |
+
return $res;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Escape string
|
106 |
+
* @param string $str
|
107 |
+
* @return string
|
108 |
+
*/
|
109 |
+
public function escapeString($str)
|
110 |
+
{
|
111 |
+
return mysqli_real_escape_string($this->conn, $str);
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Escape table name
|
116 |
+
* @param string $table
|
117 |
+
* @return string
|
118 |
+
*/
|
119 |
+
public function escapeTableName($table)
|
120 |
+
{
|
121 |
+
return self::TABLE_ESCAPER.$this->escapeString($table).self::TABLE_ESCAPER;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Escape field name
|
126 |
+
* @param stirng $fld
|
127 |
+
* @return string
|
128 |
+
*/
|
129 |
+
public function escapeFieldName($fld)
|
130 |
+
{
|
131 |
+
return self::TABLE_ESCAPER.$this->escapeString($fld).self::TABLE_ESCAPER;
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Escape field value
|
136 |
+
* @param $data
|
137 |
+
* @return string
|
138 |
+
*/
|
139 |
+
public function escapeFieldValue($data)
|
140 |
+
{
|
141 |
+
return self::VALUE_ESCAPER.$this->escapeString($data).self::VALUE_ESCAPER;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Fetch all rows
|
146 |
+
* @param $sql
|
147 |
+
* @return array
|
148 |
+
*/
|
149 |
+
public function fetchAll($sql)
|
150 |
+
{
|
151 |
+
$res = $this->query($sql);
|
152 |
+
for($out = array(); $row = $res->fetch_array($this->fetch_mode); $out[] = $row);
|
153 |
+
return $out;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Fetch one row
|
158 |
+
* @param $sql
|
159 |
+
* @return array
|
160 |
+
*/
|
161 |
+
public function fetchOne($sql)
|
162 |
+
{
|
163 |
+
$res = $this->query($sql);
|
164 |
+
return $res->fetch_array($this->fetch_mode);
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Fetch rows grouped by key
|
169 |
+
* @param $sql
|
170 |
+
* @param $key
|
171 |
+
* @param $arrayMode force Array mode
|
172 |
+
* @return array
|
173 |
+
*/
|
174 |
+
public function fetchGroupedArrayByKey($sql, $key, $arrayMode = true)
|
175 |
+
{
|
176 |
+
$res = $this->query($sql);
|
177 |
+
$out = array();
|
178 |
+
while($row = $res->fetch_array(MYSQLI_ASSOC)) {
|
179 |
+
if($arrayMode) {
|
180 |
+
if(!isset($out[$row[$key]])) {
|
181 |
+
$out[$row[$key]] = array();
|
182 |
+
}
|
183 |
+
$out[$row[$key]][] = $row;
|
184 |
+
} else {
|
185 |
+
$out[$row[$key]] = $row;
|
186 |
+
}
|
187 |
+
}
|
188 |
+
return $out;
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Fetch one field from all rows and place to list
|
193 |
+
* @param string $sql
|
194 |
+
* @param string $fld
|
195 |
+
* @return array
|
196 |
+
*/
|
197 |
+
public function fetchOneFieldAll($sql, $fld)
|
198 |
+
{
|
199 |
+
$res = $this->query($sql);
|
200 |
+
for($out = array(); $row = $res->fetch_array($this->fetch_mode); $out[] = $row[$fld]);
|
201 |
+
return $out;
|
202 |
+
}
|
203 |
+
|
204 |
+
/**
|
205 |
+
* List one item
|
206 |
+
* @param $table
|
207 |
+
* @param $condition
|
208 |
+
* @return array
|
209 |
+
*/
|
210 |
+
public function listOne($table, $condition)
|
211 |
+
{
|
212 |
+
$table = $this->escapeTableName($table);
|
213 |
+
$sql = "SELECT * FROM {$table} WHERE {$condition}";
|
214 |
+
return $this->fetchOne($sql);
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* List items in table by condition
|
219 |
+
* @param string $table table name
|
220 |
+
* @param string $condition optional, if empty 1=1 is used
|
221 |
+
* @return array
|
222 |
+
*/
|
223 |
+
public function listAll($table, $condition = '1=1')
|
224 |
+
{
|
225 |
+
$table = $this->escapeTableName($table);
|
226 |
+
$sql = "SELECT * FROM {$table} WHERE {$condition}";
|
227 |
+
return $this->fetchAll($sql);
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* List by key single entry
|
232 |
+
* @param string $table table name
|
233 |
+
* @param string $value field value
|
234 |
+
* @param string $key field name
|
235 |
+
* @return array
|
236 |
+
*/
|
237 |
+
public function listByKeyOne($table, $value, $key = 'id')
|
238 |
+
{
|
239 |
+
$table = $this->escapeTableName($table);
|
240 |
+
$key = $this->escapeFieldName($key);
|
241 |
+
$value = $this->escapeFieldValue($value);
|
242 |
+
$sql = "SELECT * FROM {$table} WHERE {$key} = {$value}";
|
243 |
+
return $this->fetchOne($sql);
|
244 |
+
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
* List by key all rows in table
|
248 |
+
* @param string $table table name
|
249 |
+
* @param string $value value of key field
|
250 |
+
* @param string $key key field name
|
251 |
+
* @param string $add additional conditions
|
252 |
+
* @return array
|
253 |
+
*/
|
254 |
+
public function listByKeyAll($table, $value, $key = 'id', $add = '')
|
255 |
+
{
|
256 |
+
$table = $this->escapeTableName($table);
|
257 |
+
$key = $this->escapeFieldName($key);
|
258 |
+
$value = $this->escapeFieldValue($value);
|
259 |
+
$sql = "SELECT * FROM {$table} WHERE {$key} = {$value} {$add}";
|
260 |
+
return $this->fetchAll($sql);
|
261 |
+
}
|
262 |
+
|
263 |
+
/**
|
264 |
+
* List by key grouped
|
265 |
+
* @param string $table
|
266 |
+
* @param string $key
|
267 |
+
* @param bool $forcedArrayMode
|
268 |
+
* @return array
|
269 |
+
*/
|
270 |
+
public function listByKeyGrouped($table, $key = 'id', $forcedArrayMode = false)
|
271 |
+
{
|
272 |
+
$table = $this->escapeTableName($table);
|
273 |
+
$sql = "SELECT * FROM {$table}";
|
274 |
+
return $this->fetchGroupedArrayByKey($sql, $key, $forcedArrayMode);
|
275 |
+
}
|
276 |
+
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Escape field names
|
280 |
+
* @param array $arrNames
|
281 |
+
* @return array
|
282 |
+
*/
|
283 |
+
public function escapeFieldNames(array $arrNames)
|
284 |
+
{
|
285 |
+
$out = array();
|
286 |
+
for ($i=0, $c = count($arrNames) ; $i<$c; $i++) {
|
287 |
+
$out[] = $this->escapeFieldName($arrNames[$i]);
|
288 |
+
}
|
289 |
+
return $out;
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* Escape field values
|
294 |
+
* @param array $arrNames
|
295 |
+
* @return array
|
296 |
+
*/
|
297 |
+
public function escapeFieldValues(array $arrNames)
|
298 |
+
{
|
299 |
+
$out = array();
|
300 |
+
for ($i=0, $c = count($arrNames) ; $i<$c; $i++) {
|
301 |
+
if($arrNames[$i] !== 'LAST_INSERT_ID()') {
|
302 |
+
$out[] = $this->escapeFieldValue($arrNames[$i]);
|
303 |
+
} else {
|
304 |
+
$out[] = $arrNames[$i];
|
305 |
+
}
|
306 |
+
}
|
307 |
+
return $out;
|
308 |
+
}
|
309 |
+
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Throw connect exception
|
313 |
+
* @throws Mage_DB_Exception
|
314 |
+
* @return void
|
315 |
+
*/
|
316 |
+
protected function throwConnectException()
|
317 |
+
{
|
318 |
+
throw new Mage_DB_Exception($this->conn->connect_error);
|
319 |
+
}
|
320 |
+
|
321 |
+
/**
|
322 |
+
* Query - perform with throwing exception on error
|
323 |
+
* @param sting $sql query
|
324 |
+
* @throws Mage_DB_Exception
|
325 |
+
* @return mixed
|
326 |
+
*/
|
327 |
+
public function query($sql)
|
328 |
+
{
|
329 |
+
$res = $this->unsafeQuery($sql);
|
330 |
+
if(!$res) {
|
331 |
+
throw new Mage_DB_Exception($this->conn->error);
|
332 |
+
}
|
333 |
+
return $res;
|
334 |
+
}
|
335 |
+
|
336 |
+
/**
|
337 |
+
* Unsafe query - perform without error checking
|
338 |
+
* @param string $sql query
|
339 |
+
* @return mixed
|
340 |
+
*/
|
341 |
+
public function unsafeQuery($sql)
|
342 |
+
{
|
343 |
+
return $this->conn->query($sql);
|
344 |
+
}
|
345 |
+
|
346 |
+
/**
|
347 |
+
* Insert assoc array to table
|
348 |
+
* @param string $table
|
349 |
+
* @param array $data
|
350 |
+
* @param bool $replace
|
351 |
+
* @return mixed
|
352 |
+
*/
|
353 |
+
public function insertAssocOne($table, array $data, $replace = false) {
|
354 |
+
$keys = $this->escapeFieldNames(array_keys($data));
|
355 |
+
$keys = "(" . implode (",", $keys) . ")";
|
356 |
+
$table = $this->escapeTableName($table);
|
357 |
+
$sql = $replace ? "REPLACE INTO {$table} " : "INSERT INTO {$table} ";
|
358 |
+
$values = $this->escapeFieldValues(array_values($data));
|
359 |
+
$values = " VALUES (" . implode (",", $values) . ")";
|
360 |
+
$sql .= $keys . $values;
|
361 |
+
return $this->query($sql);
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Insert several records to table
|
366 |
+
* @param string $table
|
367 |
+
* @param array $data
|
368 |
+
* @param bool $replace use REPLACE INTO instead of INSERT INTO
|
369 |
+
* @return array
|
370 |
+
*/
|
371 |
+
public function insertAssocMultiple($table, array $data, $replace = false, $excludeFields = array())
|
372 |
+
{
|
373 |
+
$table = $this->escapeTableName($table);
|
374 |
+
$sql = $replace ? "REPLACE INTO {$table} " : "INSERT INTO {$table} ";
|
375 |
+
$keys = array_keys($data[0]);
|
376 |
+
$excluded = array();
|
377 |
+
for($i = 0, $c = count($excludeFields); $i < $c; $i++) {
|
378 |
+
$k = $excludeFields[$i];
|
379 |
+
if(isset($keys[$k])) {
|
380 |
+
$excluded [] = $k;
|
381 |
+
unset($keys[$k]);
|
382 |
+
}
|
383 |
+
}
|
384 |
+
|
385 |
+
$keys = $this->escapeFieldNames($keys);
|
386 |
+
$sql .= " ( ";
|
387 |
+
for($i = 0, $c = count($keys); $i<$c; $i++) {
|
388 |
+
$sql .= $keys[$i];
|
389 |
+
if($i!=$c-1) {
|
390 |
+
$sql .= ",";
|
391 |
+
}
|
392 |
+
}
|
393 |
+
$sql .= " ) VALUES ";
|
394 |
+
for($i = 0, $c = count($data); $i<$c; $i++) {
|
395 |
+
$row = $data[$i];
|
396 |
+
for ($j = 0, $jc = count($excluded); $j<$jc; $j++) {
|
397 |
+
unset($data[$excluded[$j]]);
|
398 |
+
}
|
399 |
+
$values = $this->escapeFieldValues(array_values($row));
|
400 |
+
$sql .= "( ";
|
401 |
+
for ($j = 0, $jc = count($values); $j < $jc; $j++) {
|
402 |
+
$sql .= $values[$j];
|
403 |
+
if($j != $jc-1) {
|
404 |
+
$sql .= ",";
|
405 |
+
}
|
406 |
+
}
|
407 |
+
$sql .= " )";
|
408 |
+
if($i!=$c-1) {
|
409 |
+
$sql .= ",";
|
410 |
+
}
|
411 |
+
}
|
412 |
+
return $this->query($sql);
|
413 |
+
}
|
414 |
+
|
415 |
+
|
416 |
+
/**
|
417 |
+
* Set table data by condition
|
418 |
+
* @param $table
|
419 |
+
* @param $data
|
420 |
+
* @param $condition
|
421 |
+
* @return mixed
|
422 |
+
*/
|
423 |
+
public function updateAssoc($table, array $data, $condition = '1=1')
|
424 |
+
{
|
425 |
+
$table = $this->escapeTableName($table);
|
426 |
+
$set = array();
|
427 |
+
foreach($data as $k=>$v) {
|
428 |
+
$k = $this->escapeFieldName($k);
|
429 |
+
$v = $this->escapeFieldValue($v);
|
430 |
+
$set[] = $k . " = " . $v;
|
431 |
+
}
|
432 |
+
$set = implode(",", $set);
|
433 |
+
$sql = "UPDATE {$table} SET {$set} WHERE {$condition}";
|
434 |
+
return $this->query($sql);
|
435 |
+
}
|
436 |
+
|
437 |
+
|
438 |
+
/**
|
439 |
+
* Update entry by pk
|
440 |
+
* @param string $table
|
441 |
+
* @param array $data
|
442 |
+
* @param string $value
|
443 |
+
* @param string $key
|
444 |
+
* @return mixed
|
445 |
+
*/
|
446 |
+
public function updateAssocByKey($table, array $data, $value, $key = 'id')
|
447 |
+
{
|
448 |
+
$table = $this->escapeTableName($table);
|
449 |
+
$key = $this->escapeFieldName($key);
|
450 |
+
$value = $this->escapeFieldValue($value);
|
451 |
+
$set = array();
|
452 |
+
foreach($data as $k=>$v) {
|
453 |
+
$k = $this->escapeFieldName($k);
|
454 |
+
$v = $this->escapeFieldValue($v);
|
455 |
+
$set[] = $k . " = " . $v;
|
456 |
+
}
|
457 |
+
$set = implode(",", $set);
|
458 |
+
$sql = "UPDATE {$table} SET {$set} WHERE {$key} = {$value}";
|
459 |
+
return $this->query($sql);
|
460 |
+
}
|
461 |
+
|
462 |
+
|
463 |
+
/**
|
464 |
+
* Convert ids to string
|
465 |
+
* @param array|string $ids
|
466 |
+
* @return string
|
467 |
+
*/
|
468 |
+
public function idsToString($ids)
|
469 |
+
{
|
470 |
+
if(is_scalar($ids)) {
|
471 |
+
return $this->escapeFieldValue(strval($ids));
|
472 |
+
}
|
473 |
+
$out = array();
|
474 |
+
foreach ($values as $id) {
|
475 |
+
$out .= $this->escapeFieldValue($id);
|
476 |
+
}
|
477 |
+
return implode(",", $out);
|
478 |
+
}
|
479 |
+
|
480 |
+
/**
|
481 |
+
* Ids equality condition
|
482 |
+
* @param mixed $ids array or string
|
483 |
+
* @return string
|
484 |
+
*/
|
485 |
+
public function idsEqualCondition($ids)
|
486 |
+
{
|
487 |
+
$vals = $this->idsToString($ids);
|
488 |
+
$condition = is_scalar($ids) ? " = {$vals} " : " IN ({$vals}) ";
|
489 |
+
return $condition;
|
490 |
+
}
|
491 |
+
|
492 |
+
|
493 |
+
/**
|
494 |
+
* Delete items by id
|
495 |
+
* @param string $table
|
496 |
+
* @param mixed $ids array or string
|
497 |
+
* @param string $key key field
|
498 |
+
* @return mixed
|
499 |
+
*/
|
500 |
+
public function deleteById($table, $ids, $key = 'id')
|
501 |
+
{
|
502 |
+
$key = $this->escapeFieldName($key);
|
503 |
+
$cond = $this->idsEqualCondition($ids);
|
504 |
+
$table = $this->escapeTableName($table);
|
505 |
+
$sql = "DELETE FROM {$table} WHERE {$key} {$cond}";
|
506 |
+
return $this->query($sql);
|
507 |
+
}
|
508 |
+
|
509 |
+
/**
|
510 |
+
* Count items in table by condition
|
511 |
+
* @param string $table
|
512 |
+
* @param string $condition ex: "a>0"
|
513 |
+
* @return int
|
514 |
+
*/
|
515 |
+
public function simpleCount($table, $condition) {
|
516 |
+
$sql = "SELECT count(*) AS `cnt` WHERE {$condition}";
|
517 |
+
$data = $this->fetchOne($sql);
|
518 |
+
if(empty($data['cnt'])) {
|
519 |
+
return 0;
|
520 |
+
}
|
521 |
+
return intval($data['cnt']);
|
522 |
+
|
523 |
+
}
|
524 |
+
|
525 |
+
public function lastInsertId()
|
526 |
+
{
|
527 |
+
$sql = "SELECT LAST_INSERT_ID() as `id`";
|
528 |
+
$data = $this->fetchOne($sql);
|
529 |
+
return $data['id'];
|
530 |
+
}
|
531 |
+
|
532 |
+
}
|
lib/Mage/Exception.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class for Exception
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_Exception extends Exception
|
35 |
+
{}
|
lib/Mage/HTTP/Client.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Factory for HTTP client classes
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
|
35 |
+
class Mage_HTTP_Client
|
36 |
+
{
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Disallow to instantiate - pvt constructor
|
40 |
+
*/
|
41 |
+
private function __construct()
|
42 |
+
{
|
43 |
+
|
44 |
+
}
|
45 |
+
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Factory for HTTP client
|
49 |
+
* @param string/false $frontend 'curl'/'socket' or false for auto-detect
|
50 |
+
* @return Mage_HTTP_IClient
|
51 |
+
*/
|
52 |
+
public static function getInstance($frontend = false)
|
53 |
+
{
|
54 |
+
if(false === $frontend)
|
55 |
+
{
|
56 |
+
$frontend = self::detectFrontend();
|
57 |
+
}
|
58 |
+
if(false === $frontend)
|
59 |
+
{
|
60 |
+
throw new Exception("Cannot find frontend automatically, set it manually");
|
61 |
+
}
|
62 |
+
|
63 |
+
$class = __CLASS__."_".str_replace(' ', DIRECTORY_SEPARATOR, ucwords(str_replace('_', ' ', $frontend)));
|
64 |
+
$obj = new $class();
|
65 |
+
return $obj;
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Detects frontend type.
|
70 |
+
* Priority is given to CURL
|
71 |
+
*
|
72 |
+
* @return string/bool
|
73 |
+
*/
|
74 |
+
protected static function detectFrontend()
|
75 |
+
{
|
76 |
+
if(function_exists("curl_init")) {
|
77 |
+
return "curl";
|
78 |
+
}
|
79 |
+
if(function_exists("fsockopen")) {
|
80 |
+
return "socket";
|
81 |
+
}
|
82 |
+
return false;
|
83 |
+
}
|
84 |
+
}
|
lib/Mage/HTTP/Client/Curl.php
ADDED
@@ -0,0 +1,499 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not recreive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with HTTP protocol using curl library
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_HTTP_Client_Curl
|
35 |
+
implements Mage_HTTP_IClient
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Hostname
|
39 |
+
* @var string
|
40 |
+
*/
|
41 |
+
protected $_host = 'localhost';
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Port
|
45 |
+
* @var int
|
46 |
+
*/
|
47 |
+
protected $_port = 80;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Stream resource
|
51 |
+
* @var object
|
52 |
+
*/
|
53 |
+
protected $_sock = null;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Request headers
|
57 |
+
* @var array
|
58 |
+
*/
|
59 |
+
protected $_headers = array();
|
60 |
+
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Fields for POST method - hash
|
64 |
+
* @var array
|
65 |
+
*/
|
66 |
+
protected $_postFields = array();
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Request cookies
|
70 |
+
* @var array
|
71 |
+
*/
|
72 |
+
protected $_cookies = array();
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Response headers
|
76 |
+
* @var array
|
77 |
+
*/
|
78 |
+
protected $_responseHeaders = array();
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Response body
|
82 |
+
* @var string
|
83 |
+
*/
|
84 |
+
protected $_responseBody = '';
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Response status
|
88 |
+
* @var int
|
89 |
+
*/
|
90 |
+
protected $_responseStatus = 0;
|
91 |
+
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Request timeout
|
95 |
+
* @var intunknown_type
|
96 |
+
*/
|
97 |
+
protected $_timeout = 300;
|
98 |
+
|
99 |
+
/**
|
100 |
+
* TODO
|
101 |
+
* @var int
|
102 |
+
*/
|
103 |
+
protected $_redirectCount = 0;
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Curl
|
107 |
+
* @var object
|
108 |
+
*/
|
109 |
+
protected $_ch;
|
110 |
+
|
111 |
+
|
112 |
+
/**
|
113 |
+
* User ovverides options hash
|
114 |
+
* Are applied before curl_exec
|
115 |
+
*
|
116 |
+
* @var array();
|
117 |
+
*/
|
118 |
+
protected $_curlUserOptions = array();
|
119 |
+
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Header count, used while parsing headers
|
123 |
+
* in CURL callback function
|
124 |
+
* @var int
|
125 |
+
*/
|
126 |
+
protected $_headerCount = 0;
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Set request timeout, msec
|
130 |
+
*
|
131 |
+
* @param int $value
|
132 |
+
*/
|
133 |
+
public function setTimeout($value)
|
134 |
+
{
|
135 |
+
$this->_timeout = (int) $value;
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Constructor
|
140 |
+
*/
|
141 |
+
public function __construct()
|
142 |
+
{
|
143 |
+
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Set headers from hash
|
148 |
+
|
149 |
+
* @param array $headers
|
150 |
+
*/
|
151 |
+
public function setHeaders($headers)
|
152 |
+
{
|
153 |
+
$this->_headers = $headers;
|
154 |
+
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Add header
|
159 |
+
*
|
160 |
+
* @param $name name, ex. "Location"
|
161 |
+
* @param $value value ex. "http://google.com"
|
162 |
+
*/
|
163 |
+
public function addHeader($name, $value)
|
164 |
+
{
|
165 |
+
$this->_headers[$name] = $value;
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Remove specified header
|
170 |
+
*
|
171 |
+
* @param string $name
|
172 |
+
*/
|
173 |
+
public function removeHeader($name)
|
174 |
+
{
|
175 |
+
unset($this->_headers[$name]);
|
176 |
+
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Authorization: Basic header
|
181 |
+
* Login credentials support
|
182 |
+
*
|
183 |
+
* @param string $login username
|
184 |
+
* @param string $pass password
|
185 |
+
*/
|
186 |
+
public function setCredentials($login, $pass)
|
187 |
+
{
|
188 |
+
$val= base64_encode( "$login:$pass" );
|
189 |
+
$this->addHeader( "Authorization", "Basic $val" );
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Add cookie
|
194 |
+
*
|
195 |
+
* @param string $name
|
196 |
+
* @param string $value
|
197 |
+
*/
|
198 |
+
public function addCookie($name, $value)
|
199 |
+
{
|
200 |
+
$this->_cookies[$name] = $value;
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Remove cookie
|
205 |
+
*
|
206 |
+
* @param string $name
|
207 |
+
*/
|
208 |
+
public function removeCookie($name)
|
209 |
+
{
|
210 |
+
unset($this->_cookies[$name]);
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Set cookies array
|
215 |
+
*
|
216 |
+
* @param array $cookies
|
217 |
+
*/
|
218 |
+
public function setCookies($cookies)
|
219 |
+
{
|
220 |
+
$this->_cookies = $cookies;
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
* Clear cookies
|
225 |
+
*/
|
226 |
+
public function removeCookies()
|
227 |
+
{
|
228 |
+
$this->setCookies(array());
|
229 |
+
}
|
230 |
+
|
231 |
+
|
232 |
+
/**
|
233 |
+
* Make GET request
|
234 |
+
*
|
235 |
+
* @param string $uri uri relative to host, ex. "/index.php"
|
236 |
+
*/
|
237 |
+
public function get($uri)
|
238 |
+
{
|
239 |
+
$this->makeRequest("GET", $uri);
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Make POST request
|
244 |
+
* @see lib/Mage/HTTP/Mage_HTTP_Client#post($uri, $params)
|
245 |
+
*/
|
246 |
+
public function post($uri, $params)
|
247 |
+
{
|
248 |
+
$this->makeRequest("POST", $uri, $params);
|
249 |
+
}
|
250 |
+
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Get response headers
|
254 |
+
*
|
255 |
+
* @return array
|
256 |
+
*/
|
257 |
+
public function getHeaders()
|
258 |
+
{
|
259 |
+
return $this->_responseHeaders;
|
260 |
+
}
|
261 |
+
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Get response body
|
265 |
+
*
|
266 |
+
* @return string
|
267 |
+
*/
|
268 |
+
public function getBody()
|
269 |
+
{
|
270 |
+
return $this->_responseBody;
|
271 |
+
}
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Get cookies response hash
|
275 |
+
*
|
276 |
+
* @return array
|
277 |
+
*/
|
278 |
+
public function getCookies()
|
279 |
+
{
|
280 |
+
if(empty($this->_responseHeaders['Set-Cookie'])) {
|
281 |
+
return array();
|
282 |
+
}
|
283 |
+
$out = array();
|
284 |
+
foreach( $this->_responseHeaders['Set-Cookie'] as $row) {
|
285 |
+
$values = explode("; ", $row);
|
286 |
+
$c = count($values);
|
287 |
+
if(!$c) {
|
288 |
+
continue;
|
289 |
+
}
|
290 |
+
list($key, $val) = explode("=", $values[0]);
|
291 |
+
if(is_null($val)) {
|
292 |
+
continue;
|
293 |
+
}
|
294 |
+
$out[trim($key)] = trim($val);
|
295 |
+
}
|
296 |
+
return $out;
|
297 |
+
}
|
298 |
+
|
299 |
+
|
300 |
+
/**
|
301 |
+
* Get cookies array with details
|
302 |
+
* (domain, expire time etc)
|
303 |
+
* @return array
|
304 |
+
*/
|
305 |
+
public function getCookiesFull()
|
306 |
+
{
|
307 |
+
if(empty($this->_responseHeaders['Set-Cookie'])) {
|
308 |
+
return array();
|
309 |
+
}
|
310 |
+
$out = array();
|
311 |
+
foreach( $this->_responseHeaders['Set-Cookie'] as $row) {
|
312 |
+
$values = explode("; ", $row);
|
313 |
+
$c = count($values);
|
314 |
+
if(!$c) {
|
315 |
+
continue;
|
316 |
+
}
|
317 |
+
list($key, $val) = explode("=", $values[0]);
|
318 |
+
if(is_null($val)) {
|
319 |
+
continue;
|
320 |
+
}
|
321 |
+
$out[trim($key)] = array('value'=>trim($val));
|
322 |
+
array_shift($values);
|
323 |
+
$c--;
|
324 |
+
if(!$c) {
|
325 |
+
continue;
|
326 |
+
}
|
327 |
+
for($i = 0; $i<$c; $i++) {
|
328 |
+
list($subkey, $val) = explode("=", $values[$i]);
|
329 |
+
$out[trim($key)][trim($subkey)] = trim($val);
|
330 |
+
}
|
331 |
+
}
|
332 |
+
return $out;
|
333 |
+
}
|
334 |
+
|
335 |
+
/**
|
336 |
+
* Get response status code
|
337 |
+
* @see lib/Mage/HTTP/Mage_HTTP_Client#getStatus()
|
338 |
+
*/
|
339 |
+
public function getStatus()
|
340 |
+
{
|
341 |
+
return $this->_responseStatus;
|
342 |
+
}
|
343 |
+
|
344 |
+
/**
|
345 |
+
* Make request
|
346 |
+
* @param string $method
|
347 |
+
* @param string $uri
|
348 |
+
* @param array $params
|
349 |
+
* @return null
|
350 |
+
*/
|
351 |
+
protected function makeRequest($method, $uri, $params = array())
|
352 |
+
{
|
353 |
+
$this->_ch = curl_init();
|
354 |
+
$this->curlOption(CURLOPT_URL, $uri);
|
355 |
+
if($method == 'POST') {
|
356 |
+
$this->curlOption(CURLOPT_POST, 1);
|
357 |
+
$this->curlOption(CURLOPT_POSTFIELDS, http_build_query($params));
|
358 |
+
} elseif($method == "GET") {
|
359 |
+
$this->curlOption(CURLOPT_HTTPGET, 1);
|
360 |
+
} else {
|
361 |
+
$this->curlOption(CURLOPT_CUSTOMREQUEST, $method);
|
362 |
+
}
|
363 |
+
|
364 |
+
if(count($this->_headers)) {
|
365 |
+
$heads = array();
|
366 |
+
foreach($this->_headers as $k=>$v) {
|
367 |
+
$heads[] = $k.': '.$v;
|
368 |
+
}
|
369 |
+
$this->curlOption(CURLOPT_HTTPHEADER, $heads);
|
370 |
+
}
|
371 |
+
|
372 |
+
if(count($this->_cookies)) {
|
373 |
+
$cookies = array();
|
374 |
+
foreach($this->_cookies as $k=>$v) {
|
375 |
+
$cookies[] = "$k=$v";
|
376 |
+
}
|
377 |
+
$this->curlOption(CURLOPT_COOKIE, implode(";", $cookies));
|
378 |
+
}
|
379 |
+
|
380 |
+
if($this->_timeout) {
|
381 |
+
$this->curlOption(CURLOPT_TIMEOUT, $this->_timeout);
|
382 |
+
}
|
383 |
+
|
384 |
+
if($this->_port != 80) {
|
385 |
+
$this->curlOption(CURLOPT_PORT, $this->_port);
|
386 |
+
}
|
387 |
+
|
388 |
+
//$this->curlOption(CURLOPT_HEADER, 1);
|
389 |
+
$this->curlOption(CURLOPT_RETURNTRANSFER, 1);
|
390 |
+
$this->curlOption(CURLOPT_HEADERFUNCTION, array($this,'parseHeaders'));
|
391 |
+
|
392 |
+
|
393 |
+
if(count($this->_curlUserOptions)) {
|
394 |
+
foreach($this->_curlUserOptions as $k=>$v) {
|
395 |
+
$this->curlOption($k, $v);
|
396 |
+
}
|
397 |
+
}
|
398 |
+
|
399 |
+
$this->_headerCount = 0;
|
400 |
+
$this->_responseHeaders = array();
|
401 |
+
$this->_responseBody = curl_exec($this->_ch);
|
402 |
+
$err = curl_errno($this->_ch);
|
403 |
+
if($err) {
|
404 |
+
$this->doError(curl_error($this->_ch));
|
405 |
+
}
|
406 |
+
curl_close($this->_ch);
|
407 |
+
}
|
408 |
+
|
409 |
+
/**
|
410 |
+
* Throw error excpetion
|
411 |
+
* @param $string
|
412 |
+
* @throws Exception
|
413 |
+
*/
|
414 |
+
public function doError($string)
|
415 |
+
{
|
416 |
+
throw new Exception($string);
|
417 |
+
}
|
418 |
+
|
419 |
+
|
420 |
+
/**
|
421 |
+
* Parse headers - CURL callback functin
|
422 |
+
*
|
423 |
+
* @param resource $ch curl handle, not needed
|
424 |
+
* @param string $data
|
425 |
+
* @return int
|
426 |
+
*/
|
427 |
+
protected function parseHeaders($ch, $data)
|
428 |
+
{
|
429 |
+
if($this->_headerCount == 0) {
|
430 |
+
|
431 |
+
$line = explode(" ", trim($data), 3);
|
432 |
+
if(count($line) != 3) {
|
433 |
+
return $this->doError("Invalid response line returned from server: ".$data);
|
434 |
+
}
|
435 |
+
$this->_responseStatus = intval($line[1]);
|
436 |
+
} else {
|
437 |
+
//var_dump($data);
|
438 |
+
$name = $value = '';
|
439 |
+
$out = explode(": ", trim($data), 2);
|
440 |
+
if(count($out) == 2) {
|
441 |
+
$name = $out[0];
|
442 |
+
$value = $out[1];
|
443 |
+
}
|
444 |
+
|
445 |
+
if(strlen($name)) {
|
446 |
+
if("Set-Cookie" == $name) {
|
447 |
+
if(!isset($this->_responseHeaders[$name])) {
|
448 |
+
$this->_responseHeaders[$name] = array();
|
449 |
+
}
|
450 |
+
$this->_responseHeaders[$name][] = $value;
|
451 |
+
} else {
|
452 |
+
$this->_responseHeaders[$name] = $value;
|
453 |
+
}
|
454 |
+
}
|
455 |
+
|
456 |
+
}
|
457 |
+
$this->_headerCount++;
|
458 |
+
|
459 |
+
|
460 |
+
return strlen($data);
|
461 |
+
}
|
462 |
+
|
463 |
+
/**
|
464 |
+
* Set curl option directly
|
465 |
+
*
|
466 |
+
* @param string $name
|
467 |
+
* @param string $value
|
468 |
+
*/
|
469 |
+
protected function curlOption($name, $value)
|
470 |
+
{
|
471 |
+
curl_setopt($this->_ch, $name, $value);
|
472 |
+
}
|
473 |
+
|
474 |
+
/**
|
475 |
+
* Set curl options array directly
|
476 |
+
* @param array $array
|
477 |
+
*/
|
478 |
+
protected function curlOptions($array)
|
479 |
+
{
|
480 |
+
curl_setopt_array($this->_ch, $arr);
|
481 |
+
}
|
482 |
+
|
483 |
+
/**
|
484 |
+
* Set CURL options ovverides array *
|
485 |
+
*/
|
486 |
+
public function setOptions($arr)
|
487 |
+
{
|
488 |
+
$this->_curlUserOptions = $arr;
|
489 |
+
}
|
490 |
+
|
491 |
+
/**
|
492 |
+
* Set curl option
|
493 |
+
*/
|
494 |
+
public function setOption($name, $value)
|
495 |
+
{
|
496 |
+
$this->_curlUserOptions[$name] = $value;
|
497 |
+
}
|
498 |
+
|
499 |
+
}
|
lib/Mage/HTTP/Client/Socket.php
ADDED
@@ -0,0 +1,537 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Class to work with HTTP protocol using sockets
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
class Mage_HTTP_Client_Socket
|
35 |
+
implements Mage_HTTP_IClient
|
36 |
+
{
|
37 |
+
/**
|
38 |
+
* Hostname
|
39 |
+
* @var string
|
40 |
+
*/
|
41 |
+
private $_host = 'localhost';
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Port
|
45 |
+
* @var int
|
46 |
+
*/
|
47 |
+
private $_port = 80;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Stream resource
|
51 |
+
* @var object
|
52 |
+
*/
|
53 |
+
private $_sock = null;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Request headers
|
57 |
+
* @var array
|
58 |
+
*/
|
59 |
+
private $_headers = array();
|
60 |
+
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Fields for POST method - hash
|
64 |
+
* @var array
|
65 |
+
*/
|
66 |
+
private $_postFields = array();
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Request cookies
|
70 |
+
* @var array
|
71 |
+
*/
|
72 |
+
private $_cookies = array();
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Response headers
|
76 |
+
* @var array
|
77 |
+
*/
|
78 |
+
private $_responseHeaders = array();
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Response body
|
82 |
+
* @var string
|
83 |
+
*/
|
84 |
+
private $_responseBody = '';
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Response status
|
88 |
+
* @var int
|
89 |
+
*/
|
90 |
+
private $_responseStatus = 0;
|
91 |
+
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Request timeout
|
95 |
+
* @var int
|
96 |
+
*/
|
97 |
+
private $_timeout = 300;
|
98 |
+
|
99 |
+
/**
|
100 |
+
* TODO
|
101 |
+
* @var int
|
102 |
+
*/
|
103 |
+
private $_redirectCount = 0;
|
104 |
+
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Set request timeout, msec
|
108 |
+
*
|
109 |
+
* @param int $value
|
110 |
+
*/
|
111 |
+
public function setTimeout($value)
|
112 |
+
{
|
113 |
+
$this->_timeout = (int) $value;
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Constructor
|
118 |
+
* @param string $host
|
119 |
+
* @param int $port
|
120 |
+
*/
|
121 |
+
public function __construct($host = null, $port = 80)
|
122 |
+
{
|
123 |
+
if($host) {
|
124 |
+
$this->connect($host, (int) $port);
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Set connection params
|
130 |
+
*
|
131 |
+
* @param string $host
|
132 |
+
* @param int $port
|
133 |
+
*/
|
134 |
+
public function connect($host, $port = 80)
|
135 |
+
{
|
136 |
+
$this->_host = $host;
|
137 |
+
$this->_port = (int) $port;
|
138 |
+
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Disconnect
|
143 |
+
*/
|
144 |
+
public function disconnect()
|
145 |
+
{
|
146 |
+
@fclose($this->_sock);
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Set headers from hash
|
151 |
+
|
152 |
+
* @param array $headers
|
153 |
+
*/
|
154 |
+
public function setHeaders($headers)
|
155 |
+
{
|
156 |
+
$this->_headers = $headers;
|
157 |
+
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Add header
|
162 |
+
*
|
163 |
+
* @param $name name, ex. "Location"
|
164 |
+
* @param $value value ex. "http://google.com"
|
165 |
+
*/
|
166 |
+
public function addHeader($name, $value)
|
167 |
+
{
|
168 |
+
$this->_headers[$name] = $value;
|
169 |
+
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Remove specified header
|
174 |
+
*
|
175 |
+
* @param string $name
|
176 |
+
*/
|
177 |
+
public function removeHeader($name)
|
178 |
+
{
|
179 |
+
unset($this->_headers[$name]);
|
180 |
+
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Authorization: Basic header
|
185 |
+
* Login credentials support
|
186 |
+
*
|
187 |
+
* @param string $login username
|
188 |
+
* @param string $pass password
|
189 |
+
*/
|
190 |
+
public function setCredentials($login, $pass)
|
191 |
+
{
|
192 |
+
$val= base64_encode( "$login:$pass" );
|
193 |
+
$this->addHeader( "Authorization", "Basic $val" );
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Add cookie
|
198 |
+
*
|
199 |
+
* @param string $name
|
200 |
+
* @param string $value
|
201 |
+
*/
|
202 |
+
public function addCookie($name, $value)
|
203 |
+
{
|
204 |
+
$this->_cookies[$name] = $value;
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Remove cookie
|
209 |
+
*
|
210 |
+
* @param string $name
|
211 |
+
*/
|
212 |
+
public function removeCookie($name)
|
213 |
+
{
|
214 |
+
unset($this->_cookies[$name]);
|
215 |
+
}
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Set cookies array
|
219 |
+
*
|
220 |
+
* @param array $cookies
|
221 |
+
*/
|
222 |
+
public function setCookies($cookies)
|
223 |
+
{
|
224 |
+
$this->_cookies = $cookies;
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Clear cookies
|
229 |
+
*/
|
230 |
+
public function removeCookies()
|
231 |
+
{
|
232 |
+
$this->setCookies(array());
|
233 |
+
}
|
234 |
+
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Make GET request
|
238 |
+
*
|
239 |
+
* @param string $uri full uri path
|
240 |
+
*/
|
241 |
+
public function get($uri)
|
242 |
+
{
|
243 |
+
$this->makeRequest("GET",$this->parseUrl($uri));
|
244 |
+
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
* Set host, port from full url
|
248 |
+
* and return relative url
|
249 |
+
*
|
250 |
+
* @param string $uri ex. http://google.com/index.php?a=b
|
251 |
+
* @return string ex. /index.php?a=b
|
252 |
+
*/
|
253 |
+
protected function parseUrl($uri)
|
254 |
+
{
|
255 |
+
$parts = parse_url($uri);
|
256 |
+
if(!empty($parts['user']) && !empty($parts['pass'])) {
|
257 |
+
$this->setCredentials($parts['user'], $parts['pass']);
|
258 |
+
}
|
259 |
+
if(!empty($parts['port'])) {
|
260 |
+
$this->_port = (int) $parts['port'];
|
261 |
+
}
|
262 |
+
|
263 |
+
if(!empty($parts['host'])) {
|
264 |
+
$this->_host = $parts['host'];
|
265 |
+
} else {
|
266 |
+
throw new InvalidArgumentException("Uri doesn't contain host part");
|
267 |
+
}
|
268 |
+
|
269 |
+
|
270 |
+
if(!empty($parts['path'])) {
|
271 |
+
$requestUri = $parts['path'];
|
272 |
+
} else {
|
273 |
+
throw new InvalidArgumentException("Uri doesn't contain path part");
|
274 |
+
}
|
275 |
+
if(!empty($parts['query'])) {
|
276 |
+
$requestUri .= "?".$parts['query'];
|
277 |
+
}
|
278 |
+
return $requestUri;
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
* Make POST request
|
283 |
+
*/
|
284 |
+
public function post($uri, $params)
|
285 |
+
{
|
286 |
+
$this->makeRequest("POST", $this->parseUrl($uri), $params);
|
287 |
+
}
|
288 |
+
|
289 |
+
|
290 |
+
/**
|
291 |
+
* Get response headers
|
292 |
+
*
|
293 |
+
* @return array
|
294 |
+
*/
|
295 |
+
public function getHeaders()
|
296 |
+
{
|
297 |
+
return $this->_responseHeaders;
|
298 |
+
}
|
299 |
+
|
300 |
+
|
301 |
+
/**
|
302 |
+
* Get response body
|
303 |
+
*
|
304 |
+
* @return string
|
305 |
+
*/
|
306 |
+
public function getBody()
|
307 |
+
{
|
308 |
+
return $this->_responseBody;
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Get cookies response hash
|
313 |
+
*
|
314 |
+
* @return array
|
315 |
+
*/
|
316 |
+
public function getCookies()
|
317 |
+
{
|
318 |
+
if(empty($this->_responseHeaders['Set-Cookie'])) {
|
319 |
+
return array();
|
320 |
+
}
|
321 |
+
$out = array();
|
322 |
+
foreach( $this->_responseHeaders['Set-Cookie'] as $row) {
|
323 |
+
$values = explode("; ", $row);
|
324 |
+
$c = count($values);
|
325 |
+
if(!$c) {
|
326 |
+
continue;
|
327 |
+
}
|
328 |
+
list($key, $val) = explode("=", $values[0]);
|
329 |
+
if(is_null($val)) {
|
330 |
+
continue;
|
331 |
+
}
|
332 |
+
$out[trim($key)] = trim($val);
|
333 |
+
}
|
334 |
+
return $out;
|
335 |
+
}
|
336 |
+
|
337 |
+
|
338 |
+
/**
|
339 |
+
* Get cookies array with details
|
340 |
+
* (domain, expire time etc)
|
341 |
+
* @return array
|
342 |
+
*/
|
343 |
+
public function getCookiesFull()
|
344 |
+
{
|
345 |
+
if(empty($this->_responseHeaders['Set-Cookie'])) {
|
346 |
+
return array();
|
347 |
+
}
|
348 |
+
$out = array();
|
349 |
+
foreach( $this->_responseHeaders['Set-Cookie'] as $row) {
|
350 |
+
$values = explode("; ", $row);
|
351 |
+
$c = count($values);
|
352 |
+
if(!$c) {
|
353 |
+
continue;
|
354 |
+
}
|
355 |
+
list($key, $val) = explode("=", $values[0]);
|
356 |
+
if(is_null($val)) {
|
357 |
+
continue;
|
358 |
+
}
|
359 |
+
$out[trim($key)] = array('value'=>trim($val));
|
360 |
+
array_shift($values);
|
361 |
+
$c--;
|
362 |
+
if(!$c) {
|
363 |
+
continue;
|
364 |
+
}
|
365 |
+
for($i = 0; $i<$c; $i++) {
|
366 |
+
list($subkey, $val) = explode("=", $values[$i]);
|
367 |
+
$out[trim($key)][trim($subkey)] = trim($val);
|
368 |
+
}
|
369 |
+
}
|
370 |
+
return $out;
|
371 |
+
}
|
372 |
+
|
373 |
+
/**
|
374 |
+
* Process response headers
|
375 |
+
*/
|
376 |
+
protected function processResponseHeaders()
|
377 |
+
{
|
378 |
+
$crlf = "\r\n";
|
379 |
+
$this->_responseHeaders = array();
|
380 |
+
while (!feof($this->_sock)) {
|
381 |
+
$line = fgets($this->_sock, 1024);
|
382 |
+
if($line === $crlf) {
|
383 |
+
return;
|
384 |
+
}
|
385 |
+
$name = $value = '';
|
386 |
+
$out = explode(": ", trim($line), 2);
|
387 |
+
if(count($out) == 2) {
|
388 |
+
$name = $out[0];
|
389 |
+
$value = $out[1];
|
390 |
+
}
|
391 |
+
if(!empty($value)) {
|
392 |
+
if($name == "Set-Cookie") {
|
393 |
+
if(!isset($this->_responseHeaders[$name])) {
|
394 |
+
$this->_responseHeaders[$name] = array();
|
395 |
+
}
|
396 |
+
$this->_responseHeaders[$name][] = $value;
|
397 |
+
} else {
|
398 |
+
$this->_responseHeaders[$name] = $value;
|
399 |
+
}
|
400 |
+
}
|
401 |
+
}
|
402 |
+
}
|
403 |
+
|
404 |
+
/**
|
405 |
+
* Process response body
|
406 |
+
*/
|
407 |
+
protected function processResponseBody()
|
408 |
+
{
|
409 |
+
$this->_responseBody = '';
|
410 |
+
|
411 |
+
while (!feof($this->_sock)) {
|
412 |
+
$this->_responseBody .= @fread($this->_sock, 1024);
|
413 |
+
}
|
414 |
+
}
|
415 |
+
|
416 |
+
/**
|
417 |
+
* Process response
|
418 |
+
*/
|
419 |
+
protected function processResponse()
|
420 |
+
{
|
421 |
+
$response = '';
|
422 |
+
$responseLine = trim(fgets($this->_sock, 1024));
|
423 |
+
|
424 |
+
$line = explode(" ", $responseLine, 3);
|
425 |
+
if(count($line) != 3) {
|
426 |
+
return $this->doError("Invalid response line returned from server: ".$responseLine);
|
427 |
+
}
|
428 |
+
$this->_responseStatus = intval($line[1]);
|
429 |
+
$this->processResponseHeaders();
|
430 |
+
|
431 |
+
$this->processRedirect();
|
432 |
+
|
433 |
+
$this->processResponseBody();
|
434 |
+
}
|
435 |
+
|
436 |
+
|
437 |
+
/**
|
438 |
+
* Process redirect
|
439 |
+
*/
|
440 |
+
protected function processRedirect()
|
441 |
+
{
|
442 |
+
// TODO: implement redircets support
|
443 |
+
}
|
444 |
+
|
445 |
+
|
446 |
+
/**
|
447 |
+
* Get response status code
|
448 |
+
* @see lib/Mage/HTTP/Mage_HTTP_Client#getStatus()
|
449 |
+
*/
|
450 |
+
public function getStatus()
|
451 |
+
{
|
452 |
+
return $this->_responseStatus;
|
453 |
+
}
|
454 |
+
|
455 |
+
/**
|
456 |
+
* Make request
|
457 |
+
* @param string $method
|
458 |
+
* @param string $uri
|
459 |
+
* @param array $params
|
460 |
+
* @return null
|
461 |
+
*/
|
462 |
+
protected function makeRequest($method, $uri, $params = array())
|
463 |
+
{
|
464 |
+
$errno = $errstr = '';
|
465 |
+
$this->_sock = @fsockopen($this->_host, $this->_port, $errno, $errstr, $this->_timeout);
|
466 |
+
if(!$this->_sock) {
|
467 |
+
return $this->doError(sprintf("[errno: %d] %s", $errno, $errstr));
|
468 |
+
}
|
469 |
+
|
470 |
+
$crlf = "\r\n";
|
471 |
+
$isPost = $method == "POST";
|
472 |
+
|
473 |
+
$appendHeaders = array();
|
474 |
+
$paramsStr = false;
|
475 |
+
if($isPost && count($params)) {
|
476 |
+
$paramsStr = http_build_query($params);
|
477 |
+
$appendHeaders['Content-type'] = 'application/x-www-form-urlencoded';
|
478 |
+
$appendHeaders['Content-length'] = strlen($paramsStr);
|
479 |
+
}
|
480 |
+
|
481 |
+
$out = "{$method} {$uri} HTTP/1.1{$crlf}";
|
482 |
+
$out .= $this->headersToString($appendHeaders);
|
483 |
+
$out .= $crlf;
|
484 |
+
if($paramsStr) {
|
485 |
+
$out .= $paramsStr.$crlf;
|
486 |
+
}
|
487 |
+
|
488 |
+
fwrite($this->_sock, $out);
|
489 |
+
$this->processResponse();
|
490 |
+
}
|
491 |
+
|
492 |
+
/**
|
493 |
+
* Throw error excpetion
|
494 |
+
* @param $string
|
495 |
+
* @throws Exception
|
496 |
+
*/
|
497 |
+
public function doError($string)
|
498 |
+
{
|
499 |
+
throw new Exception($string);
|
500 |
+
}
|
501 |
+
|
502 |
+
/**
|
503 |
+
* Convert headers hash to string
|
504 |
+
* @param $delimiter
|
505 |
+
* @param $append
|
506 |
+
* @return string
|
507 |
+
*/
|
508 |
+
protected function headersToString($append = array())
|
509 |
+
{
|
510 |
+
$headers = array();
|
511 |
+
$headers["Host"] = $this->_host;
|
512 |
+
$headers['Connection'] = "close";
|
513 |
+
$headers = array_merge($headers, $this->_headers, $append);
|
514 |
+
$str = array();
|
515 |
+
foreach ($headers as $k=>$v) {
|
516 |
+
$str []= "$k: $v\r\n";
|
517 |
+
}
|
518 |
+
return implode($str);
|
519 |
+
}
|
520 |
+
|
521 |
+
/**
|
522 |
+
* TODO
|
523 |
+
*/
|
524 |
+
public function setOptions($arr)
|
525 |
+
{
|
526 |
+
// Stub
|
527 |
+
}
|
528 |
+
|
529 |
+
/**
|
530 |
+
* TODO
|
531 |
+
*/
|
532 |
+
public function setOption($name, $value)
|
533 |
+
{
|
534 |
+
// Stub
|
535 |
+
}
|
536 |
+
|
537 |
+
}
|
lib/Mage/HTTP/IClient.php
ADDED
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Interface for different HTTP clients
|
29 |
+
*
|
30 |
+
* @category Mage
|
31 |
+
* @package Mage_Connect
|
32 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
33 |
+
*/
|
34 |
+
interface Mage_HTTP_IClient
|
35 |
+
{
|
36 |
+
/**
|
37 |
+
* Set request timeout
|
38 |
+
* @param int $value
|
39 |
+
*/
|
40 |
+
function setTimeout($value);
|
41 |
+
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Set request headers from hash
|
45 |
+
* @param array $headers
|
46 |
+
*/
|
47 |
+
function setHeaders($headers);
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Add header to request
|
51 |
+
* @param string $name
|
52 |
+
* @param string $value
|
53 |
+
*/
|
54 |
+
function addHeader($name, $value);
|
55 |
+
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Remove header from request
|
59 |
+
* @param string $name
|
60 |
+
*/
|
61 |
+
function removeHeader($name);
|
62 |
+
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Set login credentials
|
66 |
+
* for basic auth.
|
67 |
+
* @param string $login
|
68 |
+
* @param string $pass
|
69 |
+
*/
|
70 |
+
function setCredentials($login, $pass);
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Add cookie to request
|
74 |
+
* @param string $name
|
75 |
+
* @param string $value
|
76 |
+
*/
|
77 |
+
function addCookie($name, $value);
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Remove cookie from request
|
81 |
+
* @param string $name
|
82 |
+
*/
|
83 |
+
function removeCookie($name);
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Set request cookies from hash
|
87 |
+
* @param array $cookies
|
88 |
+
*/
|
89 |
+
function setCookies($cookies);
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Remove cookies from request
|
93 |
+
*/
|
94 |
+
function removeCookies();
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Make GET request
|
98 |
+
* @param string full uri
|
99 |
+
*/
|
100 |
+
function get($uri);
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Make POST request
|
104 |
+
* @param string $uri full uri
|
105 |
+
* @param array $params POST fields array
|
106 |
+
*/
|
107 |
+
function post($uri, $params);
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Get response headers
|
111 |
+
* @return array
|
112 |
+
*/
|
113 |
+
function getHeaders();
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Get response body
|
117 |
+
* @return string
|
118 |
+
*/
|
119 |
+
function getBody();
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Get response status code
|
123 |
+
* @return int
|
124 |
+
*/
|
125 |
+
function getStatus();
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Get response cookies (k=>v)
|
129 |
+
* @return array
|
130 |
+
*/
|
131 |
+
function getCookies();
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Set additional option
|
135 |
+
* @param string $key
|
136 |
+
* @param string $value
|
137 |
+
*/
|
138 |
+
function setOption($key, $value);
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Set additional options
|
142 |
+
* @param array $arr
|
143 |
+
*/
|
144 |
+
function setOptions($arr);
|
145 |
+
}
|
lib/Mage/System/Args.php
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Magento
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
* If you did not receive a copy of the license and are unable to
|
12 |
+
* obtain it through the world-wide-web, please send an email
|
13 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
14 |
+
*
|
15 |
+
* DISCLAIMER
|
16 |
+
*
|
17 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
18 |
+
* versions in the future. If you wish to customize Magento for your
|
19 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
20 |
+
*
|
21 |
+
* @category Mage
|
22 |
+
* @package Mage_Connect
|
23 |
+
* @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
|
24 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
25 |
+
*/
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Command-line options parsing class.
|
29 |
+
*/
|
30 |
+
class Mage_System_Args
|
31 |
+
{
|
32 |
+
public $flags;
|
33 |
+
public $filtered;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Get flags/named options
|
37 |
+
* @return array
|
38 |
+
*/
|
39 |
+
public function getFlags()
|
40 |
+
{
|
41 |
+
return $this->flags;
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Get filtered args
|
46 |
+
* @return array
|
47 |
+
*/
|
48 |
+
public function getFiltered()
|
49 |
+
{
|
50 |
+
return $this->filtered;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Constructor
|
55 |
+
* @param array $argv, if false $GLOBALS['argv'] is taken
|
56 |
+
* @return void
|
57 |
+
*/
|
58 |
+
public function __construct($source = false)
|
59 |
+
{
|
60 |
+
$this->flags = array();
|
61 |
+
$this->filtered = array();
|
62 |
+
|
63 |
+
if(false === $source) {
|
64 |
+
$argv = $GLOBALS['argv'];
|
65 |
+
array_shift($argv);
|
66 |
+
}
|
67 |
+
|
68 |
+
for($i = 0, $iCount = count($argv); $i < $iCount; $i++)
|
69 |
+
{
|
70 |
+
$str = $argv[$i];
|
71 |
+
|
72 |
+
// --foo
|
73 |
+
if(strlen($str) > 2 && substr($str, 0, 2) == '--')
|
74 |
+
{
|
75 |
+
$str = substr($str, 2);
|
76 |
+
$parts = explode('=', $str);
|
77 |
+
$this->flags[$parts[0]] = true;
|
78 |
+
|
79 |
+
// Does not have an =, so choose the next arg as its value
|
80 |
+
if(count($parts) == 1 && isset($argv[$i + 1]) && preg_match('/^--?.+/', $argv[$i + 1]) == 0)
|
81 |
+
{
|
82 |
+
$this->flags[$parts[0]] = $argv[$i + 1];
|
83 |
+
$argv[$i + 1] = null;
|
84 |
+
}
|
85 |
+
elseif(count($parts) == 2) // Has a =, so pick the second piece
|
86 |
+
{
|
87 |
+
$this->flags[$parts[0]] = $parts[1];
|
88 |
+
}
|
89 |
+
}
|
90 |
+
elseif(strlen($str) == 2 && $str[0] == '-') // -a
|
91 |
+
{
|
92 |
+
$this->flags[$str[1]] = true;
|
93 |
+
if(isset($argv[$i + 1]) && preg_match('/^--?.+/', $argv[$i + 1]) == 0) {
|
94 |
+
$this->flags[$str[1]] = $argv[$i + 1];
|
95 |
+
$argv[$i + 1] = null;
|
96 |
+
}
|
97 |
+
} else if(!is_null($str)) {
|
98 |
+
$this->filtered[] = $str;
|
99 |
+
}
|
100 |
+
}
|
101 |
+
}
|
102 |
+
}
|
lib/Mage/System/Dirs.php
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
|
4 |
+
class Mage_System_Dirs
|
5 |
+
{
|
6 |
+
|
7 |
+
public static function rm($dirname)
|
8 |
+
{
|
9 |
+
if(is_array($dirname)) {
|
10 |
+
$dirname = $dirname[1];
|
11 |
+
}
|
12 |
+
// Sanity check
|
13 |
+
if (!@file_exists($dirname)) {
|
14 |
+
return false;
|
15 |
+
}
|
16 |
+
|
17 |
+
// Simple delete for a file
|
18 |
+
if (@is_file($dirname) || @is_link($dirname)) {
|
19 |
+
return unlink($dirname);
|
20 |
+
}
|
21 |
+
|
22 |
+
// Create and iterate stack
|
23 |
+
$stack = array($dirname);
|
24 |
+
while ($entry = array_pop($stack)) {
|
25 |
+
// Watch for symlinks
|
26 |
+
if (@is_link($entry)) {
|
27 |
+
@unlink($entry);
|
28 |
+
continue;
|
29 |
+
}
|
30 |
+
|
31 |
+
// Attempt to remove the directory
|
32 |
+
if (@rmdir($entry)) {
|
33 |
+
continue;
|
34 |
+
}
|
35 |
+
|
36 |
+
// Otherwise add it to the stack
|
37 |
+
$stack[] = $entry;
|
38 |
+
$dh = opendir($entry);
|
39 |
+
while (false !== $child = readdir($dh)) {
|
40 |
+
// Ignore pointers
|
41 |
+
if ($child === '.' || $child === '..') {
|
42 |
+
continue;
|
43 |
+
}
|
44 |
+
// Unlink files and add directories to stack
|
45 |
+
$child = $entry . DIRECTORY_SEPARATOR . $child;
|
46 |
+
if (is_dir($child) && !is_link($child)) {
|
47 |
+
$stack[] = $child;
|
48 |
+
} else {
|
49 |
+
@unlink($child);
|
50 |
+
}
|
51 |
+
}
|
52 |
+
@closedir($dh);
|
53 |
+
}
|
54 |
+
return true;
|
55 |
+
}
|
56 |
+
|
57 |
+
|
58 |
+
public static function mkdirStrict($path, $recursive = true, $mode = 0777)
|
59 |
+
{
|
60 |
+
$exists = file_exists($path);
|
61 |
+
if($exists && is_dir($path)) {
|
62 |
+
return true;
|
63 |
+
}
|
64 |
+
if($exists && !is_dir($path)) {
|
65 |
+
throw new Exception("'{$path}' already exists, should be a dir, not a file!");
|
66 |
+
}
|
67 |
+
$out = @mkdir($path, $mode, $recursive);
|
68 |
+
if(false === $out) {
|
69 |
+
throw new Exception("Can't create dir: '{$path}'");
|
70 |
+
}
|
71 |
+
return true;
|
72 |
+
}
|
73 |
+
|
74 |
+
public static function copyFileStrict($source, $dest)
|
75 |
+
{
|
76 |
+
$exists = file_exists($source);
|
77 |
+
if(!$exists) {
|
78 |
+
throw new Exception('No file exists: '.$exists);
|
79 |
+
}
|
80 |
+
|
81 |
+
}
|
82 |
+
}
|
lib/Mage/Xml/Generator.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Mage_Xml_Generator
|
3 |
+
{
|
4 |
+
protected $_dom = null;
|
5 |
+
protected $_currentDom;
|
6 |
+
|
7 |
+
public function __construct()
|
8 |
+
{
|
9 |
+
$this->_dom = new DOMDocument('1.0');
|
10 |
+
$this->_dom->formatOutput=true;
|
11 |
+
$this->_currentDom = $this->_dom;
|
12 |
+
return $this;
|
13 |
+
}
|
14 |
+
|
15 |
+
public function getDom()
|
16 |
+
{
|
17 |
+
return $this->_dom;
|
18 |
+
}
|
19 |
+
|
20 |
+
protected function _getCurrentDom()
|
21 |
+
{
|
22 |
+
return $this->_currentDom;
|
23 |
+
}
|
24 |
+
|
25 |
+
protected function _setCurrentDom($node)
|
26 |
+
{
|
27 |
+
$this->_currentDom = $node;
|
28 |
+
return $this;
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @param array $content
|
33 |
+
*/
|
34 |
+
public function arrayToXml($content)
|
35 |
+
{
|
36 |
+
$parentNode = $this->_getCurrentDom();
|
37 |
+
if(!$content || !count($content)) {
|
38 |
+
return $this;
|
39 |
+
}
|
40 |
+
foreach ($content as $_key=>$_item) {
|
41 |
+
try{
|
42 |
+
$node = $this->getDom()->createElement($_key);
|
43 |
+
} catch (DOMException $e) {
|
44 |
+
// echo $e->getMessage();
|
45 |
+
var_dump($_item);
|
46 |
+
die;
|
47 |
+
}
|
48 |
+
$parentNode->appendChild($node);
|
49 |
+
if (is_array($_item) && isset($_item['_attribute'])) {
|
50 |
+
if (is_array($_item['_value'])) {
|
51 |
+
if (isset($_item['_value'][0])) {
|
52 |
+
foreach($_item['_value'] as $_k=>$_v) {
|
53 |
+
$this->_setCurrentDom($node)->arrayToXml($_v);
|
54 |
+
}
|
55 |
+
} else {
|
56 |
+
$this->_setCurrentDom($node)->arrayToXml($_item['_value']);
|
57 |
+
}
|
58 |
+
} else {
|
59 |
+
$child = $this->getDom()->createTextNode($_item['_value']);
|
60 |
+
$node->appendChild($child);
|
61 |
+
}
|
62 |
+
foreach($_item['_attribute'] as $_attributeKey=>$_attributeValue) {
|
63 |
+
$node->setAttribute($_attributeKey, $_attributeValue);
|
64 |
+
}
|
65 |
+
} elseif (is_string($_item)) {
|
66 |
+
$text = $this->getDom()->createTextNode($_item);
|
67 |
+
$node->appendChild($text);
|
68 |
+
} elseif (is_array($_item) && !isset($_item[0])) {
|
69 |
+
$this->_setCurrentDom($node)->arrayToXml($_item);
|
70 |
+
} elseif (is_array($_item) && isset($_item[0])) {
|
71 |
+
foreach($_item as $k=>$v) {
|
72 |
+
$this->_setCurrentDom($node)->arrayToXml($v);
|
73 |
+
}
|
74 |
+
}
|
75 |
+
}
|
76 |
+
return $this;
|
77 |
+
}
|
78 |
+
|
79 |
+
public function __toString()
|
80 |
+
{
|
81 |
+
return $this->getDom()->saveXML();
|
82 |
+
}
|
83 |
+
|
84 |
+
public function save($file)
|
85 |
+
{
|
86 |
+
$this->getDom()->save($file);
|
87 |
+
return $this;
|
88 |
+
}
|
89 |
+
|
90 |
+
}
|
lib/Mage/Xml/Parser.php
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Mage_Xml_Parser
|
3 |
+
{
|
4 |
+
protected $_dom = null;
|
5 |
+
protected $_currentDom;
|
6 |
+
protected $_content = array();
|
7 |
+
|
8 |
+
public function __construct()
|
9 |
+
{
|
10 |
+
$this->_dom = new DOMDocument;
|
11 |
+
$this->_currentDom = $this->_dom;
|
12 |
+
return $this;
|
13 |
+
}
|
14 |
+
|
15 |
+
public function getDom()
|
16 |
+
{
|
17 |
+
return $this->_dom;
|
18 |
+
}
|
19 |
+
|
20 |
+
protected function _getCurrentDom()
|
21 |
+
{
|
22 |
+
return $this->_currentDom;
|
23 |
+
}
|
24 |
+
|
25 |
+
protected function _setCurrentDom($node)
|
26 |
+
{
|
27 |
+
$this->_currentDom = $node;
|
28 |
+
return $this;
|
29 |
+
}
|
30 |
+
|
31 |
+
public function xmlToArray()
|
32 |
+
{
|
33 |
+
$this->_content = $this->_xmlToArray();
|
34 |
+
return $this->_content;
|
35 |
+
}
|
36 |
+
|
37 |
+
protected function _xmlToArray($currentNode=false)
|
38 |
+
{
|
39 |
+
if (!$currentNode) {
|
40 |
+
$currentNode = $this->getDom();
|
41 |
+
}
|
42 |
+
$content = array();
|
43 |
+
foreach ($currentNode->childNodes as $node) {
|
44 |
+
switch ($node->nodeType) {
|
45 |
+
case XML_ELEMENT_NODE:
|
46 |
+
|
47 |
+
$value = null;
|
48 |
+
if ($node->hasChildNodes()) {
|
49 |
+
$value = $this->_xmlToArray($node);
|
50 |
+
}
|
51 |
+
$attributes = array();
|
52 |
+
if ($node->hasAttributes()) {
|
53 |
+
foreach($node->attributes as $attribute) {
|
54 |
+
$attributes += array($attribute->name=>$attribute->value);
|
55 |
+
}
|
56 |
+
$value = array('_value'=>$value, '_attribute'=>$attributes);
|
57 |
+
}
|
58 |
+
if (isset($content[$node->nodeName])) {
|
59 |
+
if (!isset($content[$node->nodeName][0]) || !is_array($content[$node->nodeName][0])) {
|
60 |
+
$oldValue = $content[$node->nodeName];
|
61 |
+
$content[$node->nodeName] = array();
|
62 |
+
$content[$node->nodeName][] = $oldValue;
|
63 |
+
}
|
64 |
+
$content[$node->nodeName][] = $value;
|
65 |
+
} else {
|
66 |
+
$content[$node->nodeName] = $value;
|
67 |
+
}
|
68 |
+
break;
|
69 |
+
case XML_TEXT_NODE:
|
70 |
+
if (trim($node->nodeValue)) {
|
71 |
+
$content = $node->nodeValue;
|
72 |
+
}
|
73 |
+
break;
|
74 |
+
}
|
75 |
+
}
|
76 |
+
return $content;
|
77 |
+
}
|
78 |
+
|
79 |
+
public function load($file)
|
80 |
+
{
|
81 |
+
$this->getDom()->load($file);
|
82 |
+
return $this;
|
83 |
+
}
|
84 |
+
|
85 |
+
public function loadXML($string)
|
86 |
+
{
|
87 |
+
$this->getDom()->loadXML($string);
|
88 |
+
return $this;
|
89 |
+
}
|
90 |
+
|
91 |
+
}
|
package.xml
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>Lib_Mage</name>
|
4 |
+
<version>1.6.0.0</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license uri="http://opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>Mage Library</summary>
|
10 |
+
<description>Mage Library</description>
|
11 |
+
<notes>1.6.0.0</notes>
|
12 |
+
<authors><author><name>Magento Core Team</name><user>core</user><email>core@magentocommerce.com</email></author></authors>
|
13 |
+
<date>2011-08-18</date>
|
14 |
+
<time>08:29:36</time>
|
15 |
+
<contents><target name="magelib"><dir name="Mage"><dir name="Archive"><file name="Abstract.php" hash="facb355053858f94439409d8657757ff"/><file name="Bz.php" hash="bce512d3062f936f1a8c12bf5c408b64"/><file name="Gz.php" hash="0dca1839014c71886a8a93186bb993d0"/><file name="Interface.php" hash="ef441008981545b886dcab6f386a6882"/><file name="Tar.php" hash="9f09ed124af89b683897246503ea9832"/></dir><file name="Archive.php" hash="f7745fb5794efd8e0a2adaef4a3f6f12"/><dir name="Autoload"><file name="Simple.php" hash="0112e880807596fbe8822be12314f14f"/></dir><dir name="Connect"><dir name="Channel"><file name="Generator.php" hash="a1f115e909680bca8c1b1f0940244b13"/><file name="Parser.php" hash="ec2e7380ec4bca81de2795f96975e778"/><file name="VO.php" hash="870a1b9b28d85dd72b2b1e2529dca354"/></dir><dir name="Command"><file name="Channels.php" hash="12f730285615329cba0b570385009837"/><file name="Channels_Header.php" hash="934366a4daa1ebe87b25cb9dfa061798"/><file name="Config.php" hash="5091776f35732d8b0ff12c8ff3561c69"/><file name="Config_Header.php" hash="119a103ed71b326993756961b6c7c2a0"/><file name="Install.php" hash="2f7227a1f4003d6ce6edec4a0ce02e0f"/><file name="Install_Header.php" hash="71f0b6bad2f745235352d181bcc66645"/><file name="Package.php" hash="b36bdc6a3c0f6bc9d7766a37c046a481"/><file name="Package_Header.php" hash="dc3840a95f89ef844df40c585582815d"/><file name="Registry.php" hash="f9fde28940ff38dbc336335d575a295d"/><file name="Registry_Header.php" hash="559edbac0f3d267c8ca289e526b940d1"/><file name="Remote.php" hash="6f959617993d58aec974d578921b6212"/><file name="Remote_Header.php" hash="4b56cd683710de6c81241f902570ba25"/></dir><file name="Command.php" hash="0d474da0956a292aa83e88da4975c527"/><file name="Config.php" hash="511f752123ccc6c148a6a308fc3f81b2"/><file name="Converter.php" hash="1cde84613c6079050bb3824aba3b380d"/><dir name="Frontend"><file name="CLI.php" hash="86e6631d9345d5bf9d15148cfdace3bf"/></dir><file name="Frontend.php" hash="0a97c590fdc9844b225638d631315d35"/><file name="Ftp.php" hash="095b9ad01ea60418b1667732cb374d95"/><dir name="Loader"><file name="Ftp.php" hash="0ca46737d25bf0eb321414f2d8b7ced0"/></dir><file name="Loader.php" hash="009d6f986d5ff406f7e94d2b395f6e25"/><dir name="Package"><file name="Extension.php" hash="68b329da9893e34099c7d8ad5cb9c940"/><file name="Hotfix.php" hash="850bd23783a77dbf6f50b4f169c2c7b3"/><file name="Maintainer.php" hash="d41d8cd98f00b204e9800998ecf8427e"/><file name="Reader.php" hash="ca384e066ac21168e0a7aebc5da869c1"/><file name="Target.php" hash="351af5965f7870d3f4e960d402805b17"/><file name="VO.php" hash="9ffbdff9210474b68db7caddf9a5fe5a"/><file name="Writer.php" hash="431f107ab2ffd1977f74a94ae16481d1"/></dir><file name="Package.php" hash="2df5f5a222c9e45bb9e4d8c0e5e6d170"/><file name="Packager.php" hash="37df01e250a103684b37a6f0b71b3128"/><dir name="Repository"><file name="Abstract.php" hash="d41d8cd98f00b204e9800998ecf8427e"/><dir name="Channel"><file name="Abstract.php" hash="d41d8cd98f00b204e9800998ecf8427e"/><file name="Commercial.php" hash="d41d8cd98f00b204e9800998ecf8427e"/><file name="Community.php" hash="d41d8cd98f00b204e9800998ecf8427e"/><file name="Core.php" hash="d41d8cd98f00b204e9800998ecf8427e"/></dir><file name="Channel.php" hash="d41d8cd98f00b204e9800998ecf8427e"/><file name="Local.php" hash="d41d8cd98f00b204e9800998ecf8427e"/></dir><file name="Repository.php" hash="d41d8cd98f00b204e9800998ecf8427e"/><file name="Rest.php" hash="ba2d2365fc989274940e1fdff6476875"/><file name="Singleconfig.php" hash="975c04d57cbce24327e84a93d9f5443e"/><dir name="Structures"><file name="Graph.php" hash="b85283fd2af6fd54fb748cb6ea933842"/><file name="Node.php" hash="26a7e4041c3d2fd93bfdc3c692c85ede"/></dir><file name="Validator.php" hash="3ac1b21ec703073d5dd9b5dda3471fe8"/></dir><dir name="DB"><file name="Exception.php" hash="e0b55d77af8e215135ef223f593832ad"/><file name="Mysqli.php" hash="5057ea65f441bbb00c7e55298e9252a4"/></dir><file name="Exception.php" hash="9bf1aefdb7fd166d25889f36707997dc"/><dir name="HTTP"><dir name="Client"><file name="Curl.php" hash="f537a9879781ec3fe2748677bee43737"/><file name="Socket.php" hash="7a889fed729d92eba849d6fdfa32d7d6"/></dir><file name="Client.php" hash="7072f9366680bc5ebc1c447700193cb4"/><file name="IClient.php" hash="88a4a88a31a05a2154d430d7b4308ff6"/></dir><dir name="System"><file name="Args.php" hash="8080a06707f4393b9155441ed4160f4a"/><file name="Dirs.php" hash="adc832887e04f359b2ec050b0b2e6d17"/></dir><dir name="Xml"><file name="Generator.php" hash="0ddc93b0c75885f67d049d0a38c630fa"/><file name="Parser.php" hash="b2bdc0880cd5bc2d82468ee075e783a2"/></dir></dir></target></contents>
|
16 |
+
<compatible/>
|
17 |
+
<dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
|
18 |
+
</package>
|