diff --git a/module/extension/control.php b/module/extension/control.php
index e58635e656..9453137645 100644
--- a/module/extension/control.php
+++ b/module/extension/control.php
@@ -102,6 +102,7 @@ class extension extends control
}
/**
+ * 安装插件流程。
* Install a extension
*
* @param string $extension
@@ -112,143 +113,27 @@ class extension extends control
* @param string $ignoreCompatible
* @param string $overrideFile
* @param string $agreeLicense
- * @param int $upgrade
+ * @param string $upgrade
* @access public
* @return void
*/
- public function install($extension, $downLink = '', $md5 = '', $type = '', $overridePackage = 'no', $ignoreCompatible = 'no', $overrideFile = 'no', $agreeLicense = 'no', $upgrade = 'no')
+ public function install(string $extension, string $downLink = '', string $md5 = '', string $type = '', string $overridePackage = 'no', string $ignoreCompatible = 'no', string $overrideFile = 'no', string $agreeLicense = 'no', string $upgrade = 'no')
{
$this->checkSafe();
set_time_limit(0);
- $this->view->error = '';
- $installTitle = $upgrade == 'no' ? $this->lang->extension->install : $this->lang->extension->upgrade;
- $installType = $upgrade == 'no' ? $this->lang->extension->installExt : $this->lang->extension->upgradeExt;
+ $installTitle = $upgrade == 'no' ? $this->lang->extension->install : $this->lang->extension->upgrade;
+ $installType = $upgrade == 'no' ? $this->lang->extension->installExt : $this->lang->extension->upgradeExt;
+ $this->view->title = $installTitle . $extension;
$this->view->installType = $installType;
$this->view->upgrade = $upgrade;
- $this->view->title = $installTitle . $extension;
+ $this->view->error = '';
- $statusFile = $this->loadModel('common')->checkSafeFile();
- if($statusFile)
- {
- $this->view->error = sprintf($this->lang->extension->noticeOkFile, $statusFile, $statusFile);
- return $this->display();
- }
- /* Get the package file name. */
- $packageFile = $this->extension->getPackageFile($extension);
-
- /* Check the package file exists or not. */
- if(!file_exists($packageFile))
- {
- $this->view->error = sprintf($this->lang->extension->errorPackageNotFound, $packageFile);
- return $this->display();
- }
-
- /* Checking the extension paths. */
- $return = $this->extension->checkExtensionPaths($extension);
- if($this->session->dirs2Created == false) $this->session->set('dirs2Created', $return->dirs2Created, 'admin'); // Save the dirs to be created.
- if($return->result != 'ok')
- {
- $this->view->error = $return->errors;
- return $this->display();
- }
-
- /* Extract the package. */
- $return = $this->extension->extractPackage($extension);
- if($return->result != 'ok')
- {
- $this->view->error = sprintf($this->lang->extension->errorExtracted, $packageFile, $return->error);
- return $this->display();
- }
- /* Get condition. e.g. zentao|depends|conflicts. */
- $condition = $this->extension->getCondition($extension);
- $installedExts = $this->extension->getLocalExtensions('installed');
-
- /* Check version incompatible */
- $incompatible = $condition->zentao['incompatible'];
- if($this->extension->checkVersion($incompatible))
- {
- $this->view->error = $this->lang->extension->errorIncompatible;
- return $this->display();
- }
-
- /* Check conflicts. */
- $conflicts = $condition->conflicts;
- if($conflicts)
- {
- $conflictsExt = '';
- foreach($conflicts as $code => $limit)
- {
- if(isset($installedExts[$code]))
- {
- if($this->extension->compare4Limit($installedExts[$code]->version, $limit)) $conflictsExt .= $installedExts[$code]->name . " ";
- }
- }
-
- if($conflictsExt)
- {
- $this->view->error = sprintf($this->lang->extension->errorConflicts, $conflictsExt);
- return $this->display();
- }
- }
-
- /* Check Depends. */
- $depends = $condition->depends;
- if($depends)
- {
- $dependsExt = '';
- foreach($depends as $code => $limit)
- {
- $noDepends = false;
- if(isset($installedExts[$code]))
- {
- if($this->extension->compare4Limit($installedExts[$code]->version, $limit, 'noBetween')) $noDepends = true;
- }
- else
- {
- $noDepends = true;
- }
-
- $extVersion = '';
- if($limit != 'all')
- {
- $extVersion .= '(';
- if(!empty($limit['min'])) $extVersion .= '>=v' . $limit['min'];
- if(!empty($limit['max'])) $extVersion .= ' <=v' . $limit['max'];
- $extVersion .=')';
- }
- if($noDepends) $dependsExt .= $code . $extVersion . ' ' . html::a(inlink('obtain', 'type=bycode¶m=' . helper::safe64Encode($code)), $this->lang->extension->installExt, '_blank') . '
';
- }
-
- if($noDepends)
- {
- $this->view->error = sprintf($this->lang->extension->errorDepends, $dependsExt);
- return $this->display();
- }
- }
-
- /* Check version compatible. */
- $zentaoCompatible = $condition->zentao['compatible'];
- if(!$this->extension->checkVersion($zentaoCompatible) and $ignoreCompatible == 'no')
- {
- $ignoreLink = inlink('install', "extension=$extension&downLink=&md5=$md5&type=$type&overridePackage=$overridePackage&ignoreCompatible=yes&overrideFile=$overrideFile&agreeLicense=$agreeLicense&upgrade=$upgrade");
- $returnLink = inlink('obtain');
- $this->view->error = sprintf($this->lang->extension->errorCheckIncompatible, $installType, $ignoreLink, $installType, $returnLink);
- return $this->display();
- }
-
- /* Check files in the package conflicts with exists files or not. */
- if($overrideFile == 'no')
- {
- $return = $this->extension->checkFile($extension);
- if($return->result != 'ok')
- {
- $overrideLink = inlink('install', "extension=$extension&downLink=&md5=$md5&type=$type&overridePackage=$overridePackage&ignoreCompatible=$ignoreCompatible&overrideFile=yes&agreeLicense=$agreeLicense&upgrade=$upgrade");
- $returnLink = inlink('obtain');
- $this->view->error = sprintf($this->lang->extension->errorFileConflicted, $return->error, $overrideLink, $returnLink);
- return $this->display();
- }
- }
+ /* 插件安装前的合规校验。 */
+ $ignoreLink = inlink('install', "extension=$extension&downLink=&md5=$md5&type=$type&overridePackage=$overridePackage&ignoreCompatible=yes&overrideFile=$overrideFile&agreeLicense=$agreeLicense&upgrade=$upgrade");
+ $overrideLink = inlink('install', "extension=$extension&downLink=&md5=$md5&type=$type&overridePackage=$overridePackage&ignoreCompatible=$ignoreCompatible&overrideFile=yes&agreeLicense=$agreeLicense&upgrade=$upgrade");
+ $this->checkExtension($extension, $ignoreCompatible, $ignoreLink, $overrideFile, $overrideLink, $installType);
+ if($this->view->error) return $this->display();
if($upgrade == 'yes')
{
@@ -258,6 +143,7 @@ class extension extends control
$this->post->installedVersion = $oldInfo ? $oldInfo->version : '';
}
+ /* 打印授权协议同意表单。 */
/* Print the license form. */
if($agreeLicense == 'no')
{
@@ -270,43 +156,8 @@ class extension extends control
return $this->display();
}
- /* The preInstall hook file. */
- $hook = $upgrade == 'yes' ? 'preupgrade' : 'preinstall';
- if($preHookFile = $this->extension->getHookFile($extension, $hook)) include $preHookFile;
-
- /* Save to database. */
- $this->extension->saveExtension($extension, $type);
-
- /* Copy files to target directory. */
- $this->view->files = $this->extension->copyPackageFiles($extension);
-
- /* Judge need execute db install or not. */
- $data = new stdclass();
- $data->status = 'installed';
- $data->dirs = $this->session->dirs2Created;
- $data->files = $this->view->files;
- $data->installedTime = helper::now();
- $this->session->set('dirs2Created', array(), 'admin'); // clean the session.
-
- /* Execute the install.sql. */
- if($upgrade == 'no' and $this->extension->needExecuteDB($extension, 'install'))
- {
- $return = $this->extension->executeDB($extension, 'install');
- if($return->result != 'ok')
- {
- $this->view->error = sprintf($this->lang->extension->errorInstallDB, $return->error);
- return $this->display();
- }
- }
-
- /* Update status, dirs, files and installed time. */
- $this->extension->updateExtension($extension, $data);
- $this->view->downloadedPackage = false;
-
- /* The postInstall hook file. */
- $hook = $upgrade == 'yes' ? 'postupgrade' : 'postinstall';
- if($postHookFile = $this->extension->getHookFile($extension, $hook)) include $postHookFile;
-
+ /* 安装插件。 */
+ $this->installExtension($extension, $type, $upgrade);
$this->display();
}
diff --git a/module/extension/zen.php b/module/extension/zen.php
new file mode 100644
index 0000000000..006f2351cc
--- /dev/null
+++ b/module/extension/zen.php
@@ -0,0 +1,264 @@
+
+ * @package extension
+ * @link https://www.zentao.net
+ */
+class extensionZen extends extension
+{
+ /**
+ * 插件安装前的合规校验。
+ * Check before installation.
+ *
+ * @param string $extension
+ * @param string $ignoreCompatible
+ * @param string $ignoreLink
+ * @param string $overrideFile
+ * @param string $overrideLink
+ * @param string $installType
+ * @access protected
+ * @return bool
+ */
+ protected function checkExtension(string $extension, string $ignoreCompatible, string $ignoreLink, string $overrideFile, string $overrideLink, string $installType): bool
+ {
+ /* 安全性校验。 */
+ $statusFile = $this->loadModel('common')->checkSafeFile();
+ if($statusFile)
+ {
+ $this->view->error = sprintf($this->lang->extension->noticeOkFile, $statusFile, $statusFile);
+ return false;
+ }
+
+ /* Check the package file exists or not. */
+ $packageFile = $this->extension->getPackageFile($extension);
+ if(!file_exists($packageFile))
+ {
+ $this->view->error = sprintf($this->lang->extension->errorPackageNotFound, $packageFile);
+ return false;
+ }
+
+ /* Checking the extension paths. */
+ $return = $this->extension->checkExtensionPaths($extension);
+ if($this->session->dirs2Created == false) $this->session->set('dirs2Created', $return->dirs2Created, 'admin'); // Save the dirs to be created.
+ if($return->result != 'ok')
+ {
+ $this->view->error = $return->errors;
+ return false;
+ }
+
+ /* Extract the package. */
+ $return = $this->extension->extractPackage($extension);
+ if($return->result != 'ok')
+ {
+ $this->view->error = sprintf($this->lang->extension->errorExtracted, $packageFile, $return->error);
+ return false;
+ }
+
+ /* Get condition. e.g. zentao|depends|conflicts. */
+ $condition = $this->extension->getCondition($extension);
+ $installedExts = $this->extension->getLocalExtensions('installed');
+
+ if(!$this->checkCompatible($extension, $condition, $ignoreCompatible, $ignoreLink, $installType)) return false;
+ if(!$this->checkConflicts($condition, $installedExts)) return false;
+ if(!$this->checkDepends($condition, $installedExts)) return false;
+ if(!$this->checkFile($extension, $overrideFile, $overrideLink)) return false;
+
+ return true;
+ }
+
+ /**
+ * 插件兼容性检查。
+ * Extension compatibility check.
+ *
+ * @param string $extension
+ * @param object $condition
+ * @param string $ignoreCompatible
+ * @param string $ignoreLink
+ * @param string $installType
+ * @access private
+ * @return bool
+ */
+ private function checkCompatible(string $extension, object $condition, string $ignoreCompatible, string $ignoreLink, string $installType): bool
+ {
+ /* 不兼容版本检查。 */
+ /* Check version incompatible */
+ $incompatible = $condition->zentao['incompatible'];
+ if($this->extension->checkVersion($incompatible))
+ {
+ $this->view->error = $this->lang->extension->errorIncompatible;
+ return false;
+ }
+
+ /* 兼容版本检查。 */
+ /* Check version compatible. */
+ $zentaoCompatible = $condition->zentao['compatible'];
+ if(!$this->extension->checkVersion($zentaoCompatible) && $ignoreCompatible == 'no')
+ {
+ $this->view->error = sprintf($this->lang->extension->errorCheckIncompatible, $installType, $ignoreLink, $installType, inlink('obtain'));
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * 插件与插件之间的冲突检查。
+ * Check conflicts.
+ *
+ * @param object $condition
+ * @param array $installedExts
+ * @access private
+ * @return bool
+ */
+ private function checkConflicts(object $condition, array $installedExts): bool
+ {
+ $conflicts = $condition->conflicts;
+ if($conflicts)
+ {
+ $conflictsExt = '';
+ foreach($conflicts as $code => $limit)
+ {
+ if(isset($installedExts[$code]))
+ {
+ if($this->extension->compare4Limit($installedExts[$code]->version, $limit)) $conflictsExt .= $installedExts[$code]->name . " ";
+ }
+ }
+
+ if($conflictsExt)
+ {
+ $this->view->error = sprintf($this->lang->extension->errorConflicts, $conflictsExt);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 相关依赖插件检查。
+ * Check depends.
+ *
+ * @param object $condition
+ * @param array $installedExts
+ * @access private
+ * @return bool
+ */
+ private function checkDepends(object $condition, array $installedExts): bool
+ {
+ $depends = $condition->depends;
+ if($depends)
+ {
+ $dependsExt = '';
+ foreach($depends as $code => $limit)
+ {
+ $noDepends = false;
+ if(isset($installedExts[$code]))
+ {
+ if($this->extension->compare4Limit($installedExts[$code]->version, $limit, 'noBetween')) $noDepends = true;
+ }
+ else
+ {
+ $noDepends = true;
+ }
+
+ $extVersion = '';
+ if($limit != 'all')
+ {
+ $extVersion .= '(';
+ if(!empty($limit['min'])) $extVersion .= '>=v' . $limit['min'];
+ if(!empty($limit['max'])) $extVersion .= ' <=v' . $limit['max'];
+ $extVersion .=')';
+ }
+ if($noDepends) $dependsExt .= $code . $extVersion . ' ' . html::a(inlink('obtain', 'type=bycode¶m=' . helper::safe64Encode($code)), $this->lang->extension->installExt, '_blank') . '
';
+ }
+
+ if($noDepends)
+ {
+ $this->view->error = sprintf($this->lang->extension->errorDepends, $dependsExt);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 插件文件和禅道已有文件的冲突检查。
+ * Check files in the package conflicts with exists files or not.
+ *
+ * @param string $extension
+ * @param string $overrideFile
+ * @param string $overrideLink
+ * @access private
+ * @return bool
+ */
+ private function checkFile(string $extension, string $overrideFile, string $overrideLink): bool
+ {
+ if($overrideFile == 'no')
+ {
+ $return = $this->extension->checkFile($extension);
+ if($return->result != 'ok')
+ {
+ $this->view->error = sprintf($this->lang->extension->errorFileConflicted, $return->error, $overrideLink, inlink('obtain'));
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * 执行插件安装程序。
+ * Install extension.
+ *
+ * @param string $extension
+ * @param string $type
+ * @param string $upgrade
+ * @access protected
+ * @return void
+ */
+ protected function installExtension(string $extension, string $type, string $upgrade): bool
+ {
+ /* The preInstall hook file. */
+ $hook = $upgrade == 'yes' ? 'preupgrade' : 'preinstall';
+ if($preHookFile = $this->extension->getHookFile($extension, $hook)) include $preHookFile;
+
+ /* Save to database. */
+ $this->extension->saveExtension($extension, $type);
+
+ /* Copy files to target directory. */
+ $this->view->files = $this->extension->copyPackageFiles($extension);
+
+ /* Judge need execute db install or not. */
+ $data = new stdclass();
+ $data->status = 'installed';
+ $data->dirs = $this->session->dirs2Created;
+ $data->files = $this->view->files;
+ $data->installedTime = helper::now();
+ $this->session->set('dirs2Created', array(), 'admin'); // clean the session.
+
+ /* Execute the install.sql. */
+ if($upgrade == 'no' && $this->extension->needExecuteDB($extension, 'install'))
+ {
+ $return = $this->extension->executeDB($extension, 'install');
+ if($return->result != 'ok')
+ {
+ $this->view->error = sprintf($this->lang->extension->errorInstallDB, $return->error);
+ return false;
+ }
+ }
+
+ /* Update status, dirs, files and installed time. */
+ $this->extension->updateExtension($extension, $data);
+ $this->view->downloadedPackage = false;
+
+ /* The postInstall hook file. */
+ $hook = $upgrade == 'yes' ? 'postupgrade' : 'postinstall';
+ if($postHookFile = $this->extension->getHookFile($extension, $hook)) include $postHookFile;
+
+ return true;
+ }
+}