677 lines
18 KiB
PHP
677 lines
18 KiB
PHP
<?php
|
|
|
|
class PShowUpdateNew
|
|
{
|
|
|
|
/**
|
|
* @deprecated since version 58
|
|
* do not use this !
|
|
*/
|
|
public static $modulename;
|
|
public static $customercode;
|
|
public static $prestaversion;
|
|
public static $tmppath;
|
|
public static $reportbugurl = 'http://modules.prestashow.pl/bug_report.php';
|
|
public static $updateurl = 'http://modules.prestashow.pl';
|
|
public static $modulepath = null;
|
|
|
|
/**
|
|
* @var array of \PShowUpdateNew
|
|
*/
|
|
private static $instance = array();
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
private $filepath;
|
|
|
|
/**
|
|
* Get singleton instance
|
|
*
|
|
* @param string $_filepath
|
|
* @return \PShowUpdateNew
|
|
*/
|
|
public static function getInstance($_filepath)
|
|
{
|
|
$filepath = self::findRealFilePathFromBacktrace($_filepath);
|
|
$md5 = md5($filepath);
|
|
|
|
if (!array_key_exists($md5, self::$instance)) {
|
|
self::$instance[$md5] = new self($filepath);
|
|
}
|
|
|
|
return self::$instance[$md5];
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param string $filepath
|
|
* @return string
|
|
*/
|
|
public static function findRealFilePathFromBacktrace($filepath)
|
|
{
|
|
$backtrace = debug_backtrace();
|
|
|
|
foreach ($backtrace as $call) {
|
|
if (array_key_exists('file', $call) && stripos($call['file'], '/system/') === false && stripos($call['file'], '/modules/') !== false) {
|
|
return $call['file'];
|
|
}
|
|
}
|
|
|
|
// this should not happen !
|
|
return $filepath;
|
|
}
|
|
|
|
/**
|
|
* Get recommended product
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getRecommendedProduct()
|
|
{
|
|
if (!defined('PS_ADMIN_DIR')) {
|
|
return array(
|
|
'name' => 'PrestaShow.pl',
|
|
'description' => '',
|
|
'image' => '',
|
|
'url' => 'http://prestashow.pl'
|
|
);
|
|
}
|
|
|
|
if (_PS_CACHE_ENABLED_ && Cache::getInstance()->exists('pshow_recommended')) {
|
|
return Cache::getInstance()->get('pshow_recommended');
|
|
}
|
|
|
|
$context = stream_context_create(array(
|
|
'http' => array(
|
|
'method' => 'GET',
|
|
'timeout' => 1
|
|
)
|
|
));
|
|
|
|
$products = @unserialize(file_get_contents('http://modules.prestashow.pl/recommended_products/1', false, $context));
|
|
|
|
|
|
if (!$products) {
|
|
$products = array(array('name' => 'PrestaShow.pl', 'description' => '', 'image' => '', 'url' => 'http://prestashow.pl'));
|
|
}
|
|
|
|
Cache::getInstance()->set('pshow_recommended', reset($products), 60);
|
|
|
|
return reset($products);
|
|
}
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param string $filepath
|
|
*/
|
|
private function __construct($filepath)
|
|
{
|
|
$this->filepath = $filepath;
|
|
}
|
|
|
|
/**
|
|
* Get module name
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getModuleName()
|
|
{
|
|
$module_path = $this->getModulePath();
|
|
$module_path_arr = explode(DIRECTORY_SEPARATOR, $module_path);
|
|
|
|
return $module_path_arr[count($module_path_arr) - 2];
|
|
}
|
|
|
|
/**
|
|
* Get module path
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getModulePath()
|
|
{
|
|
$filepath = $this->filepath;
|
|
|
|
if (Tools::getValue('controller') && stripos(Tools::getValue('controller'), 'PShow')) {
|
|
$controller = strtolower(Tools::getValue('controller'));
|
|
|
|
$bestpath = false;
|
|
|
|
for ($i = 0; $i <= strlen($controller); ++$i) {
|
|
$tmp = _PS_MODULE_DIR_ . substr($controller, 0, $i);
|
|
$bestpath = is_dir($tmp) ? $tmp : $bestpath;
|
|
}
|
|
|
|
return $bestpath . '/';
|
|
}
|
|
|
|
if (Tools::substr($filepath, -1, 1) == DIRECTORY_SEPARATOR) {
|
|
$filepath = Tools::substr($filepath, 0, Tools::strlen($filepath) - 1);
|
|
}
|
|
|
|
$explode = explode(DIRECTORY_SEPARATOR, dirname($filepath));
|
|
|
|
$stay = array_search('modules', $explode) + 1;
|
|
|
|
if (!array_key_exists($stay, $explode)) {
|
|
return $filepath . DIRECTORY_SEPARATOR;
|
|
}
|
|
|
|
$newpath_ = array();
|
|
|
|
for ($i = 0; $i <= $stay; ++$i) {
|
|
$newpath_[] = $explode[$i];
|
|
}
|
|
|
|
$newpath = implode(DIRECTORY_SEPARATOR, $newpath_);
|
|
|
|
return $newpath . DIRECTORY_SEPARATOR;
|
|
}
|
|
|
|
/**
|
|
* Get license key
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getCustomerCode()
|
|
{
|
|
$customercode = 'no-license';
|
|
$customercode_file = $this->getModulePath($this->filepath) . "license";
|
|
|
|
// to protect license -> move code to php file
|
|
if (file_exists($customercode_file) && !file_exists($customercode_file . ".php")) {
|
|
$key = file_get_contents($customercode_file);
|
|
$key = preg_replace('/\s+/', '', $key);
|
|
file_put_contents($customercode_file . ".php", "<?php return '" . $key . "';");
|
|
}
|
|
|
|
if (file_exists($customercode_file . ".php")) {
|
|
$customercode_ = require($customercode_file . ".php");
|
|
if (is_string($customercode_)) {
|
|
$customercode = $customercode_;
|
|
}
|
|
if (file_exists($customercode_file)) {
|
|
unlink($customercode_file);
|
|
}
|
|
}
|
|
|
|
return $customercode;
|
|
}
|
|
|
|
/**
|
|
* Get module display name
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getModuleDisplayName()
|
|
{
|
|
$module_file = Tools::file_get_contents($this->getModulePath() . $this->getModuleName() . '.php');
|
|
|
|
$matches = array();
|
|
preg_match_all('~class ([a-zA-Z0-9]+) extends~', $module_file, $matches);
|
|
$_matches = end($matches);
|
|
|
|
return end($_matches);
|
|
}
|
|
|
|
/**
|
|
* Get module version number
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getModuleVersionNumber()
|
|
{
|
|
$path = $this->getModulePath() . $this->getModuleName() . '.php';
|
|
|
|
if (stripos($path, 'modules') === false || !file_exists($path)) {
|
|
return $path;
|
|
}
|
|
|
|
$module = Module::getInstanceByName($this->getModuleName());
|
|
|
|
if (!is_object($module)) {
|
|
return '0.0.0';
|
|
}
|
|
|
|
$module_version_arr = explode('.', $module->version);
|
|
if (file_exists($this->getModulePath() . 'system/version')) {
|
|
$skeleton_version = (int) Tools::file_get_contents($this->getModulePath() . 'system/version');
|
|
} else {
|
|
$skeleton_version = 0;
|
|
}
|
|
|
|
return ((int) $module_version_arr[0]) . '.' . ((int) $module_version_arr[1]) . '.' . ((int) $skeleton_version + (int) $module_version_arr[2]);
|
|
}
|
|
|
|
/**
|
|
* Get newest module version
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getNewestVersionNumber()
|
|
{
|
|
if (!defined('PS_ADMIN_DIR')) {
|
|
return 'notInAdmin';
|
|
}
|
|
|
|
$controller = Tools::getValue('controller');
|
|
if (!$controller || stripos($controller, 'Update') === false) {
|
|
return 'notInUpdatePage';
|
|
}
|
|
|
|
$url = 'http://modules.prestashow.pl';
|
|
$url .= '/' . $this->getPrestashopVersion();
|
|
$url .= '/' . $this->getModuleName();
|
|
$url .= '/' . $this->getModuleVersionNumber();
|
|
$url .= '/' . $this->getCustomerCode();
|
|
$url .= '/' . gethostbyname(gethostname());
|
|
$url .= '/' . $_SERVER["HTTP_HOST"];
|
|
|
|
// try to get version by curl
|
|
if (function_exists('curl_init')) {
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_VERBOSE, true);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
$newestVersionNumber = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($httpCode == 200) {
|
|
return $newestVersionNumber;
|
|
}
|
|
}
|
|
|
|
$headers = get_headers($url);
|
|
if (!strpos($headers[0], '200')) {
|
|
return 'Unable to check. Try again later...';
|
|
}
|
|
|
|
$context = stream_context_create(array(
|
|
'http' => array(
|
|
'method' => 'GET',
|
|
'timeout' => 3
|
|
)
|
|
));
|
|
$newestVersionNumber = @file_get_contents($url, false, $context);
|
|
if (!$newestVersionNumber || $newestVersionNumber == '0.0.0') {
|
|
return 'Unable to check. Try again later...';
|
|
}
|
|
|
|
return $newestVersionNumber;
|
|
}
|
|
|
|
/**
|
|
* Get prestashop version
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getPrestashopVersion()
|
|
{
|
|
return _PS_VERSION_;
|
|
}
|
|
|
|
/**
|
|
* Compare current module version with newest version
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function compareModuleAndNewestVersion()
|
|
{
|
|
return version_compare(
|
|
$this->getModuleVersionNumber(), $this->getNewestVersionNumber(), '>='
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Download update package
|
|
*
|
|
* @return boolean | string
|
|
*/
|
|
public function downloadUpdate()
|
|
{
|
|
|
|
$url = 'http://modules.prestashow.pl';
|
|
$url .= '/download';
|
|
$url .= '/' . $this->getPrestashopVersion();
|
|
$url .= '/' . $this->getModuleName();
|
|
$url .= '/' . $this->getModuleVersionNumber();
|
|
$url .= '/' . $this->getCustomerCode();
|
|
$url .= '/' . gethostbyname(gethostname());
|
|
$url .= '/http://' . $_SERVER["HTTP_HOST"] . __PS_BASE_URI__;
|
|
|
|
$tmppath = $this->getTmpPath();
|
|
if (!is_dir($tmppath)) {
|
|
@mkdir($tmppath);
|
|
if (!is_dir($tmppath)) {
|
|
echo 'brak katalogu ' . $tmppath;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!is_writable($this->getTmpPath())) {
|
|
echo 'brak uprawnień, ustaw uprawnienia zapisu dla katalogu ' . $tmppath;
|
|
return false;
|
|
}
|
|
|
|
if (function_exists('curl_init')) {
|
|
|
|
set_time_limit(0);
|
|
|
|
$fp = fopen($tmppath . $this->getNewestVersionNumber() . '.zip', 'w+');
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
|
|
curl_setopt($ch, CURLOPT_FILE, $fp);
|
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
|
curl_exec($ch);
|
|
curl_close($ch);
|
|
fclose($fp);
|
|
} else {
|
|
|
|
$package = Tools::file_get_contents($url);
|
|
|
|
file_put_contents($tmppath . $this->getNewestVersionNumber() . '.zip', $package);
|
|
}
|
|
|
|
return (file_exists($tmppath . $this->getNewestVersionNumber() . '.zip'));
|
|
}
|
|
|
|
/**
|
|
* Get path to the temporary fir
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getTmpPath()
|
|
{
|
|
return $this->getModulePath() . 'update/tmp/';
|
|
}
|
|
|
|
/**
|
|
* Extract update package
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function extractUpdate()
|
|
{
|
|
$version = $this->getNewestVersionNumber();
|
|
|
|
if (!file_exists($this->getTmpPath() . $version . '.zip')) {
|
|
return false;
|
|
}
|
|
|
|
$zip = new ZipArchive();
|
|
|
|
$res = $zip->open($this->getTmpPath() . $version . '.zip');
|
|
|
|
if ($res === true) {
|
|
$zip->extractTo($this->getTmpPath());
|
|
$zip->close();
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Recursively copy directory
|
|
*
|
|
* @param string $src
|
|
* @param string $dst
|
|
* @return boolean
|
|
*/
|
|
public function recurseCopy($src, $dst)
|
|
{
|
|
$dir = opendir($src);
|
|
|
|
@mkdir($dst);
|
|
|
|
while (false !== ( $file = readdir($dir))) {
|
|
if (( $file != '.' ) && ( $file != '..' ) && ( $file != 'license' )) {
|
|
if (is_dir($src . '/' . $file)) {
|
|
$this->recurseCopy($src . '/' . $file, $dst . '/' . $file);
|
|
} else {
|
|
copy($src . '/' . $file, $dst . '/' . $file);
|
|
}
|
|
}
|
|
}
|
|
closedir($dir);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Clear temporary dir
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function clearTmpDir()
|
|
{
|
|
$this->recurseRemoveDir($this->getTmpPath());
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Introduce new update into module
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function moveUpdateToModule()
|
|
{
|
|
$from = $this->getTmpPath() . $this->getModuleName() . "/";
|
|
$to = $this->getModulePath();
|
|
|
|
$this->recurseCopy($from, $to);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Recursively remove dir
|
|
*
|
|
* @param string $_path
|
|
* @param boolean $removePath
|
|
* @return boolean
|
|
*/
|
|
public function recurseRemoveDir($_path, $removePath = false)
|
|
{
|
|
if (!is_dir($_path)) {
|
|
return false;
|
|
}
|
|
|
|
$path = str_replace('//', '/', $_path);
|
|
|
|
if (Tools::substr($path, -1, 1) == DIRECTORY_SEPARATOR) {
|
|
$path = Tools::substr($path, 0, Tools::strlen($path) - 1);
|
|
}
|
|
|
|
$files = glob($path . '/*');
|
|
|
|
foreach ($files as $file) {
|
|
if (is_dir($file)) {
|
|
$this->recurseRemoveDir($file, true);
|
|
continue;
|
|
}
|
|
|
|
unlink($file);
|
|
}
|
|
|
|
if ($removePath === true) {
|
|
@rmdir($path);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create module backup package
|
|
*
|
|
* @return boolean|string
|
|
*/
|
|
public function makeModuleBackup()
|
|
{
|
|
$path = $this->getModulePath() . "update/backups/";
|
|
$destPath = $path . $this->getModuleName() . "_" . $this->getModuleVersionNumber() . "_" . date('H.i_d.m.Y') . ".zip";
|
|
|
|
$zip = new ZipArchive();
|
|
|
|
if (!is_dir($path)) {
|
|
@mkdir($path);
|
|
if (!is_dir($path)) {
|
|
return 'brak katalogu ' . $path;
|
|
}
|
|
}
|
|
|
|
if (!$zip->open($destPath, ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
|
|
return false;
|
|
}
|
|
|
|
$files = new RecursiveIteratorIterator(
|
|
new RecursiveDirectoryIterator($this->getModulePath()), RecursiveIteratorIterator::LEAVES_ONLY
|
|
);
|
|
|
|
try {
|
|
|
|
foreach ($files as $name => $file) {
|
|
if (!$file->isDir()) {
|
|
|
|
$filePath = $file->getRealPath();
|
|
$relativePath = Tools::substr($filePath, Tools::strlen($this->getModulePath()));
|
|
|
|
if (preg_match('~update~', $filePath)) {
|
|
continue;
|
|
}
|
|
|
|
if (preg_match('~.git~', $filePath)) {
|
|
continue;
|
|
}
|
|
|
|
if (preg_match('~license~', $filePath)) {
|
|
continue;
|
|
}
|
|
|
|
if (preg_match('~' . $this->getModuleName() . '_~', $filePath)) {
|
|
continue;
|
|
}
|
|
|
|
$zip->addFile($filePath, $relativePath);
|
|
}
|
|
}
|
|
} catch (UnexpectedValueException $e) {
|
|
|
|
}
|
|
|
|
$zip->close();
|
|
|
|
return (file_exists($destPath));
|
|
}
|
|
|
|
/**
|
|
* Move backup package to temporary dir
|
|
*
|
|
* @param string $file
|
|
* @return boolean
|
|
*/
|
|
public function moveBackupToTmp($file)
|
|
{
|
|
if (!file_exists($this->getModulePath() . "update/backups/" . $file)) {
|
|
return false;
|
|
}
|
|
|
|
copy($this->getModulePath() . "update/backups/" . $file, $this->getTmpPath() . $file);
|
|
|
|
if (!file_exists($this->getTmpPath() . $file)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Extract backup package
|
|
*
|
|
* @param string $file
|
|
* @return boolean
|
|
*/
|
|
public function extractBackup($file)
|
|
{
|
|
if (!file_exists($this->getTmpPath() . $file)) {
|
|
return false;
|
|
}
|
|
|
|
$zip = new ZipArchive();
|
|
|
|
$res = $zip->open($this->getTmpPath() . $file);
|
|
|
|
if (!file_exists($this->getTmpPath() . 'backup/')) {
|
|
mkdir($this->getTmpPath() . 'backup/', 0777);
|
|
}
|
|
|
|
if ($res === TRUE) {
|
|
$zip->extractTo($this->getTmpPath() . 'backup/');
|
|
$zip->close();
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Introduce backup to the module
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function moveBackupToModule()
|
|
{
|
|
$from = $this->getTmpPath() . 'backup/';
|
|
$to = $this->getModulePath();
|
|
|
|
$this->recurseCopy($from, $to);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Execute updates
|
|
*
|
|
* @param string $from_ver
|
|
* @return boolean
|
|
*/
|
|
public function execUpdate($from_ver)
|
|
{
|
|
$ver_expl = explode('.', $from_ver);
|
|
$from_ver = $ver_expl[0] . '.' . $ver_expl[1];
|
|
|
|
$modulename = $this->getModuleName();
|
|
require_once $this->getModulePath() . $modulename . '.php';
|
|
$instance = new $modulename();
|
|
|
|
if (!isset($instance->moduleVersionPath)) {
|
|
$instance->moduleVersionPath = array();
|
|
}
|
|
|
|
foreach ($instance->moduleVersionPath as $ver) {
|
|
$funcName = str_replace('.', '_', $from_ver);
|
|
|
|
if (version_compare($instance->version, $from_ver . '.0') == 1 && method_exists($instance, $funcName)) {
|
|
$instance->funcName();
|
|
}
|
|
}
|
|
|
|
//if (method_exists($instance, 'reinstallControllers')) $instance->reinstallControllers();
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Format version to display
|
|
*
|
|
* @param string $version
|
|
* @return string
|
|
*/
|
|
public function formatVersionToDisplay($version)
|
|
{
|
|
return preg_replace('/([0-9]+).([0-9]+).([0-9]+)/i', '$1.$2-$3', $version);
|
|
}
|
|
}
|