- Upgrading plugins error. The version never changes. The code is already updated. - Problema resuelto, en la actualizacion de un plugins, en el listado que se mustra en la columna Version, se mostrara la version del plugins actualizado. Disponible para la version 2.8 de ProcessMaker.
455 lines
14 KiB
PHP
455 lines
14 KiB
PHP
<?php
|
|
require_once 'classes/model/om/BaseAddonsManager.php';
|
|
require_once PATH_CORE . 'classes' . PATH_SEP . 'class.enterpriseUtils.php';
|
|
|
|
|
|
if (!defined("BUFSIZE")) {
|
|
define("BUFSIZE", 16384);
|
|
}
|
|
|
|
/**
|
|
* Skeleton subclass for representing a row from the 'UPGRADE_MANAGER' table.
|
|
*
|
|
*
|
|
*
|
|
* You should add additional methods to this class to meet the
|
|
* application requirements. This class will only be generated as
|
|
* long as it does not already exist in the output directory.
|
|
*
|
|
* @package classes.model
|
|
*/
|
|
class AddonsManager extends BaseAddonsManager
|
|
{
|
|
/**
|
|
* Returns the download filename
|
|
*
|
|
* @return string download filename
|
|
*/
|
|
|
|
public function getDownloadFilename()
|
|
{
|
|
$filename = $this->getAddonDownloadFilename();
|
|
if (!isset($filename) || empty($filename)) {
|
|
$filename = "download.tar";
|
|
}
|
|
$dir = $this->getDownloadDirectory();
|
|
return "$dir/$filename";
|
|
}
|
|
|
|
public function getDownloadDirectory()
|
|
{
|
|
$dir = PATH_DATA . "upgrade/{$this->getStoreId()}_{$this->getAddonName()}";
|
|
if (!file_exists($dir)) {
|
|
mkdir($dir, 0777, true);
|
|
}
|
|
return ($dir);
|
|
}
|
|
|
|
/**
|
|
* Check to see if the download file exists and has the right data.
|
|
*
|
|
* @return mixed true if exists and md5 is good, false otherwise. Returns null
|
|
* if file exists but md5 for the download is not available.
|
|
*/
|
|
public function checkDownload()
|
|
{
|
|
$filename = $this->getDownloadFilename();
|
|
if (!file_exists($filename)) {
|
|
return false;
|
|
}
|
|
$download_md5 = $this->getAddonDownloadMd5();
|
|
if ($download_md5 == null) {
|
|
return null;
|
|
}
|
|
return (strcasecmp(md5_file($filename), $download_md5) == 0);
|
|
}
|
|
|
|
/**
|
|
* Returns if this addon is of type 'plugin'
|
|
*
|
|
* @return bool true if is of type 'plugin', false otherwise
|
|
*/
|
|
public function isPlugin()
|
|
{
|
|
return ($this->getAddonType() == 'plugin');
|
|
}
|
|
|
|
/**
|
|
* Returns if this addon is of type 'core'
|
|
*
|
|
* @return bool true if is of type 'core', false otherwise
|
|
*/
|
|
public function isCore()
|
|
{
|
|
return ($this->getAddonType() == 'core');
|
|
}
|
|
|
|
/**
|
|
* Returns if this addon is installed or not-
|
|
*
|
|
* @return bool true if installed, false otherwise
|
|
*/
|
|
public function isInstalled()
|
|
{
|
|
if ($this->isCore()) {
|
|
return ($this->getAddonVersion() == $this->getInstalledVersion());
|
|
} elseif ($this->isPlugin()) {
|
|
return (file_exists(PATH_PLUGINS . "{$this->getAddonName()}.php"));
|
|
} else {
|
|
throw new Exception("Addon type '{$this->getAddonType()}' unsupported");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns if this addon is enabled or not.
|
|
*
|
|
* @return bool true if enabled, false otherwise
|
|
*/
|
|
public function isEnabled()
|
|
{
|
|
if ($this->isCore()) {
|
|
return $this->isInstalled();
|
|
} elseif ($this->isPlugin()) {
|
|
if (!$this->isInstalled()) {
|
|
return false;
|
|
}
|
|
$oPluginRegistry = &PMPluginRegistry::getSingleton();
|
|
$status = $oPluginRegistry->getStatusPlugin($this->getAddonName());
|
|
return (strcmp($status, "enabled") == 0);
|
|
} else {
|
|
throw new Exception("Addon type '{$this->getAddonType()}' unsupported");
|
|
}
|
|
}
|
|
|
|
public function setEnabled($enable = true)
|
|
{
|
|
if (!$this->isInstalled() || !$this->isPlugin()) {
|
|
return false;
|
|
}
|
|
if ($this->getAddonName() == "enterprise") {
|
|
return false;
|
|
}
|
|
|
|
$oPluginRegistry = &PMPluginRegistry::getSingleton();
|
|
|
|
require_once (PATH_PLUGINS . $this->getAddonName() . ".php");
|
|
|
|
if ($enable) {
|
|
//$oDetails = $oPluginRegistry->getPluginDetails($this->getAddonName());
|
|
//$oPluginRegistry->enablePlugin($oDetails->sNamespace);
|
|
//require_once (PATH_PLUGINS . $this->getAddonName() . ".php"); //ok
|
|
$oPluginRegistry->enablePlugin($this->getAddonName());
|
|
} else {
|
|
//$oDetails = $oPluginRegistry->getPluginDetails($this->getAddonName());
|
|
//$oPluginRegistry->disablePlugin($oDetails->sNamespace);
|
|
$oPluginRegistry->disablePlugin($this->getAddonName());
|
|
}
|
|
|
|
//$oPluginRegistry->setupPlugins();
|
|
file_put_contents(PATH_DATA_SITE . "plugin.singleton", $oPluginRegistry->serializeInstance());
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns the currently installed version of this addon.
|
|
*
|
|
* @return string the installed version or an empty string otherwise.
|
|
*/
|
|
public function getInstalledVersion()
|
|
{
|
|
if ($this->isCore()) {
|
|
G::LoadClass("system");
|
|
return (EnterpriseUtils::pmVersion(System::getVersion()));
|
|
} else {
|
|
if ($this->isPlugin()) {
|
|
if (!$this->isInstalled()) {
|
|
return (null);
|
|
}
|
|
|
|
$oPluginRegistry = &PMPluginRegistry::getSingleton();
|
|
$details = $oPluginRegistry->getPluginDetails($this->getAddonName() . ".php");
|
|
$v = (!($details == null))? $details->iVersion : null;
|
|
|
|
if ($v != "") {
|
|
return ($v);
|
|
}
|
|
|
|
if (file_exists(PATH_PLUGINS . $this->getAddonName() . PATH_SEP . "VERSION")) {
|
|
return (trim(file_get_contents(PATH_PLUGINS . $this->getAddonName() . PATH_SEP . "VERSION")));
|
|
}
|
|
} else {
|
|
if ($this->getAddonType() == "core") {
|
|
throw new Exception("Addon type \"" . $this->getAddonType() . "\" unsupported");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function refresh()
|
|
{
|
|
/* Update our information from the db */
|
|
$rs = $this->getPeer()->doSelectRS($this->buildPkeyCriteria());
|
|
$rs->first();
|
|
$this->hydrate($rs);
|
|
}
|
|
|
|
/**
|
|
* Download this addon from the download url.
|
|
*
|
|
* @return bool true on success, false otherwise.
|
|
*/
|
|
public function download()
|
|
{
|
|
require_once PATH_CORE . 'classes' . PATH_SEP . 'class.pmLicenseManager.php';
|
|
|
|
$this->setState("download");
|
|
|
|
///////
|
|
$aux = explode("?", $this->getAddonDownloadUrl());
|
|
|
|
$url = $aux[0];
|
|
$var = explode("&", $aux[1]);
|
|
|
|
///////
|
|
$boundary = "---------------------" . substr(md5(rand(0, 32000)), 0, 10);
|
|
$data = null;
|
|
|
|
for ($i = 0; $i <= count($var) - 1; $i++) {
|
|
$aux = explode("=", $var[$i]);
|
|
|
|
$data = $data . "--$boundary\n";
|
|
$data = $data . "Content-Disposition: form-data; name=\"" . $aux[0] . "\"\n\n" . $aux[1] . "\n";
|
|
}
|
|
|
|
if (count($var) > 0) {
|
|
$data = $data . "--$boundary\n";
|
|
}
|
|
|
|
///////
|
|
$licenseManager = &pmLicenseManager::getSingleton();
|
|
$activeLicense = $licenseManager->getActiveLicense();
|
|
|
|
$data = $data . "Content-Disposition: form-data; name=\"licenseFile\"; filename=\"" . $licenseManager->file . "\"\n";
|
|
$data = $data . "Content-Type: text/plain\n";
|
|
//$data = $data . "Content-Type: image/jpeg\n";
|
|
$data = $data . "Content-Transfer-Encoding: binary\n\n";
|
|
$data = $data . file_get_contents($activeLicense["LICENSE_PATH"]) . "\n";
|
|
$data = $data . "--$boundary\n";
|
|
|
|
///////
|
|
$option = array(
|
|
"http" => array(
|
|
"method" => "POST",
|
|
//"method" => "post",
|
|
"header" => "Content-Type: multipart/form-data; boundary=" . $boundary,
|
|
"content" => $data
|
|
)
|
|
);
|
|
|
|
// Proxy settings
|
|
$sysConf = System::getSystemConfiguration();
|
|
if ($sysConf['proxy_host'] != '') {
|
|
if (!is_array($option['http'])) {
|
|
$option['http'] = array();
|
|
}
|
|
$option['http']['request_fulluri'] = true;
|
|
$option['http']['proxy'] = 'tcp://' . $sysConf['proxy_host'] . ($sysConf['proxy_port'] != '' ? ':' . $sysConf['proxy_port'] : '');
|
|
if ($sysConf['proxy_user'] != '') {
|
|
if (!isset($option['http']['header'])) {
|
|
$option['http']['header'] = '';
|
|
}
|
|
$option['http']['header'] .= 'Proxy-Authorization: Basic ' . base64_encode($sysConf['proxy_user'] . ($sysConf['proxy_pass'] != '' ? ':' . $sysConf['proxy_pass'] : ''));
|
|
}
|
|
}
|
|
|
|
$context = stream_context_create($option);
|
|
|
|
///////
|
|
$handle = fopen($url, "rb", false, $context);
|
|
|
|
if ($handle === false) {
|
|
throw new Exception("Could not open download url.");
|
|
}
|
|
|
|
$this->setAddonDownloadFilename(null);
|
|
|
|
//Try to get the download size and filename (ok if it fails)
|
|
$meta = stream_get_meta_data($handle);
|
|
$totalSize = 0;
|
|
|
|
if ($meta["wrapper_type"] == "http") {
|
|
foreach ($meta["wrapper_data"] as $info) {
|
|
$info = explode(":", $info);
|
|
if (strcasecmp(trim($info[0]), "Content-Length") == 0) {
|
|
$totalSize = intval(trim($info[1]));
|
|
}
|
|
if (strcasecmp(trim($info[0]), "Content-Disposition") == 0) {
|
|
foreach (explode(";", $info[1]) as $params) {
|
|
$params = explode("=", $params);
|
|
if (count($params) <= 1) {
|
|
continue;
|
|
}
|
|
if (strcasecmp(trim($params[0]), "filename") == 0) {
|
|
$this->setAddonDownloadFilename(trim($params[1], "\" "));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Save the filename
|
|
$this->save();
|
|
|
|
$units = array(" B", " KB", " MB", " GB", " TB");
|
|
//if ($totalSize) {
|
|
// $bytes = $totalSize;
|
|
// for ($i = 0; $bytes >= 1024 && $i < 4; $i++) $bytes /= 1024;
|
|
// printf("Download size: %.2f%s\n", round($bytes, 2), $units[$i]);
|
|
//}
|
|
|
|
$downloadFile = $this->getDownloadFilename();
|
|
$file = @fopen($downloadFile, "wb");
|
|
|
|
if ($file === false) {
|
|
throw new Exception("Could not open destination file.");
|
|
}
|
|
|
|
$start = microtime(true);
|
|
|
|
while (!feof($handle)) {
|
|
$this->refresh();
|
|
/* Check if download was cancelled from the ui */
|
|
if ($this->getAddonState() == "cancel" || $this->getAddonState() == "") {
|
|
$this->setState();
|
|
break;
|
|
}
|
|
/* Update the database information to show we are still alive */
|
|
$this->setState("download");
|
|
$data = fread($handle, BUFSIZE);
|
|
//TODO: We should use these values for something
|
|
$elapsed = microtime(true) - $start;
|
|
$position = ftell($handle);
|
|
$rate = $position / $elapsed;
|
|
if ($totalSize) {
|
|
$progress = 100 * ($position / $totalSize);
|
|
$this->setAddonDownloadProgress($progress);
|
|
$this->save();
|
|
}
|
|
/* Just to be safe, check all error conditions */
|
|
if ($data === "" or $data === false) {
|
|
break;
|
|
}
|
|
if (fwrite($file, $data) === false) {
|
|
break;
|
|
}
|
|
}
|
|
fclose($handle);
|
|
fclose($file);
|
|
|
|
if ($elapsed > 60) {
|
|
$time = sprintf("%.0f minutes and %.0f seconds", round($elapsed / 60), round($elapsed) % 60);
|
|
} else {
|
|
$time = sprintf("%.0f seconds", round($elapsed));
|
|
}
|
|
|
|
for ($i = 0; $position >= 1024 && $i < 4; $i++) {
|
|
$position /= 1024;
|
|
}
|
|
for ($j = 0; $rate >= 1024 && $j < 4; $j++) {
|
|
$rate /= 1024;
|
|
}
|
|
//printf("Downloaded %.2f%s in %s (rate: %.2f%s/s)\n", $position, $units[$i], $time, $rate, $units[$j]);
|
|
|
|
return ($this->checkDownload());
|
|
}
|
|
|
|
/**
|
|
* Install this addon from the downloaded file.
|
|
*/
|
|
public function install()
|
|
{
|
|
$this->setState("install");
|
|
|
|
$filename = $this->getDownloadFilename();
|
|
//if ($this->checkDownload() === false) {
|
|
// throw new Exception("Download file is invalid");
|
|
//}
|
|
|
|
if ($this->isPlugin()) {
|
|
if ($this->getAddonId() == "enterprise") {
|
|
$_SESSION["__ENTERPRISE_INSTALL__"] = 1;
|
|
}
|
|
|
|
$oPluginRegistry = &PMPluginRegistry::getSingleton();
|
|
$oPluginRegistry->installPluginArchive($filename, $this->getAddonName());
|
|
|
|
$this->setState();
|
|
} else {
|
|
if ($this->getAddonType() == "core") {
|
|
require_once PATH_CORE . 'classes' . PATH_SEP . 'class.Upgrade.php';
|
|
$upgrade = new Upgrade($this);
|
|
|
|
$upgrade->install();
|
|
} else {
|
|
throw new Exception("Addon type {$this->getAddonType()} not supported.");
|
|
}
|
|
}
|
|
}
|
|
|
|
public function uninstall()
|
|
{
|
|
if ($this->isPlugin()) {
|
|
if (!$this->isInstalled()) {
|
|
return false;
|
|
}
|
|
|
|
$oPluginRegistry = &PMPluginRegistry::getSingleton();
|
|
$oPluginRegistry->uninstallPlugin($this->getAddonName());
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public function getInstallLog()
|
|
{
|
|
$logFile = $this->getDownloadDirectory() . "/download.log";
|
|
$contents = false;
|
|
if (file_exists($logFile)) {
|
|
$contents = @file_get_contents($logFile);
|
|
}
|
|
if ($contents === false) {
|
|
return null;
|
|
}
|
|
return $contents;
|
|
}
|
|
|
|
public function setState($state = "")
|
|
{
|
|
$this->setAddonState($state);
|
|
$this->setAddonStateChanged('now');
|
|
$this->save();
|
|
}
|
|
|
|
public function checkState()
|
|
{
|
|
if ($this->getAddonState() == 'error') {
|
|
$this->setState();
|
|
return false;
|
|
}
|
|
if ($this->getAddonState() == '' || $this->getAddonState() == 'install-finish') {
|
|
return true;
|
|
}
|
|
$elapsed = time() - strtotime($this->getAddonStateChanged());
|
|
$timeout = 3;
|
|
if ($this->isCore()) {
|
|
$timeout = 10;
|
|
}
|
|
if ($elapsed > $timeout * 60) {
|
|
$this->setState();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|