| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205 |
- <?php
- class upgradeZen extends upgrade
- {
- /**
- * 升级变更内容缓存。
- * Upgrade changes cache.
- *
- * @var array
- * @access private
- */
- private $upgradeChanges = [];
- /**
- * 获取要升级到的版本列表。
- * Get upgrade versions.
- *
- * @param string $fromVersion
- * @access protected
- * @return string[]
- */
- protected function getUpgradeVersions($fromVersion)
- {
- $upgradeVersions = [];
- $currentEdition = $this->config->edition;
- $fromEdition = $this->upgrade->getEditionByVersion($fromVersion);
- $fromOpenVersion = $this->upgrade->getOpenVersion(str_replace('.', '_', $this->config->installedVersion));
- if($currentEdition == 'open')
- {
- /**
- * 如果当前版本是开源版,则列出所有大于 fromVersion 的开源版版本。
- * 比如 fromVersion 为 21_7_6,当前版本为 21_7_8,则列出 21_7_7 和 21_7_8。
- * If the current edition is open, list all versions greater than fromVersion.
- * For example, if fromVersion is 21_7_6 and the current version is 21_7_8, list 21_7_7 and 21_7_8.
- */
- foreach($this->lang->upgrade->fromVersions as $version => $label)
- {
- if(!is_numeric($version[0])) continue;
- if(version_compare($version, $fromOpenVersion, '<=')) continue;
- $upgradeVersions[$version] = $label;
- }
- return $upgradeVersions;
- }
- if($currentEdition == $fromEdition)
- {
- /**
- * 如果当前版本和 fromVersion 版本属于同一付费版,则列出所有大于 fromVersion 的该付费版版本。
- * 比如 fromVersion 为 biz12_6,当前版本为 biz12_8,则列出 biz12_7 和 biz12_8。
- * If the current edition is the same as fromEdition, list all versions greater than fromVersion of the same edition.
- * For example, if fromVersion is biz12_6 and the current version is biz12_8, list biz12_7 and biz12_8.
- */
- foreach($this->lang->upgrade->fromVersions as $version => $label)
- {
- if(strpos($version, $currentEdition) !== 0) continue;
- if(version_compare($version, $fromVersion, '<=')) continue;
- $upgradeVersions[$version] = $label;
- }
- }
- else
- {
- $currentMapVersions = $this->config->upgrade->{$currentEdition . 'Version'};
- if(array_search($fromOpenVersion, $currentMapVersions))
- {
- /**
- * 如果当前版本和 fromVersion 版本属于不同付费版,但 fromVersion 可以映射到当前付费版,则列出所有大于等于 fromVersion 映射版本的该付费版版本。
- * 比如 fromVersion 为 biz12_6,当前版本为 max12_8,则列出 max12_6、max12_7 和 max12_8。
- * If the current edition is different from fromEdition, but fromVersion can be mapped to the current edition, list all versions greater than or equal to the mapped version of the current edition.
- */
- foreach($currentMapVersions as $version => $openVersion)
- {
- if(version_compare($openVersion, $fromOpenVersion, '<')) continue;
- $upgradeVersions[$version] = $this->lang->upgrade->fromVersions[$version] ?? '';
- }
- }
- else
- {
- /**
- * 查找距离 fromVersion 最近的当前付费版版本和开源版版本。
- * 比如 fromVersion 为 18_1,当前版本为 ipd4_7,则 currentMappedVersion 为 ipd1_0_beta1, currentMappedOpenVersion 为 18_4_alpha1
- * Find the nearest current edition version and open version from fromVersion.
- * For example, if fromVersion is 18_1 and the current version is ipd4_7, then currentMappedVersion is ipd1_0_beta1 and currentMappedOpenVersion is 18_4_alpha1.
- */
- $currentMappedVersion = '';
- $currentMappedOpenVersion = '';
- foreach($currentMapVersions as $version => $openVersion)
- {
- if(version_compare($openVersion, $fromOpenVersion, '>'))
- {
- $currentMappedVersion = $version;
- $currentMappedOpenVersion = $openVersion;
- break;
- }
- }
- if($fromEdition == 'open')
- {
- /**
- * 如果 fromVersion 是开源版,则列出所有大于 fromVersion 且小于距离 fromVersion 最近的当前付费版映射的开源版版本。
- * 比如 fromVersion 为 18_1,当 前版本为 ipd4_7,则列出大于 18_1 且小于 18_4_alpha1 的所有开源版版本,即 18_2 和 18_3。
- * If fromEdition is open, list all versions greater than fromVersion and less than the open version mapped by the current edition nearest to fromVersion.
- * For example, if fromVersion is 18_1 and the current version is ipd4_7, list all open versions greater than 18_1 and less than 18_4_alpha1, i.e., 18_2 and 18_3.
- */
- foreach($this->lang->upgrade->fromVersions as $version => $label)
- {
- if(!is_numeric($version[0])) continue;
- if(version_compare($version, $fromOpenVersion, '<=')) continue;
- if(!empty($currentMappedOpenVersion) && version_compare($version, $currentMappedOpenVersion, '>=')) break;
- $upgradeVersions[$version] = $label;
- }
- }
- else
- {
- /**
- * 如果 fromVersion 是付费版,则列出所有大于 fromVersion 映射的开源版版本且小于距离 fromVersion 最近的当前付费版映射的开源版版本对应的付费版版本。
- * 比如 fromVersion 为 biz8_1,当前版本为 ipd4_7,则列出大于 18_1 且小于 18_4_alpha1 的所有开源版版本对应的付费版版本,即 biz8_2 和 biz8_3。
- * If fromEdition is charged, list all open versions greater than the open version mapped by fromVersion and less than the open version mapped by the current edition nearest to fromVersion.
- * For example, if fromVersion is biz8_1 and the current version is ipd4_7, list all open versions greater than 18_1 and less than 18_4_alpha1, i.e., 18_2 and 18_3.
- */
- $fromMapVersions = $this->config->upgrade->{$fromEdition . 'Version'};
- foreach($fromMapVersions as $version => $openVersion)
- {
- if(version_compare($openVersion, $fromOpenVersion, '<=')) continue;
- if(!empty($currentMappedOpenVersion) && version_compare($openVersion, $currentMappedOpenVersion, '>=')) break;
- $upgradeVersions[$version] = $this->lang->upgrade->fromVersions[$version] ?? '';
- }
- }
- /**
- * 列出所有大于等于距离 fromVersion 最近的当前付费版版本。
- * 比如 fromVersion 为 biz8_1,当前版本为 ipd4_7,则列出 ipd1_0_beta1 及之后的所有版本。
- * List all versions greater than or equal to the current edition version nearest to fromVersion.
- * For example, if fromVersion is biz8_1 and the current version is ipd4_7, list ipd1_0_beta1 and all subsequent versions.
- */
- foreach(array_keys($currentMapVersions) as $version)
- {
- if(!empty($currentMappedVersion) && version_compare($version, $currentMappedVersion, '<')) continue;
- $upgradeVersions[$version] = $this->lang->upgrade->fromVersions[$version] ?? '';
- }
- }
- }
- $currentVersion = str_replace('.', '_', $this->config->version);
- if($currentEdition == 'ipd' && empty($upgradeVersions[$currentVersion])) $upgradeVersions[$currentVersion] = ucfirst($this->config->version);
- return $upgradeVersions;
- }
- /**
- * 获取升级变更内容列表。
- * Get upgrade changes.
- *
- * @param string $fromVersion
- * @param string $toVersion
- * @access protected
- * @return array[]
- */
- protected function getUpgradeChanges($fromVersion, $toVersion)
- {
- $this->upgradeChanges = [];
- $currentVersion = str_replace('.', '_', $this->config->installedVersion);
- $fromEdition = $this->upgrade->getEditionByVersion($fromVersion);
- $fromOpenVersion = $this->upgrade->getOpenVersion($currentVersion);
- $toOpenVersion = $this->upgrade->getOpenVersion($toVersion);
- $upgradeVersions = $this->upgrade->getVersionsToUpdate($fromOpenVersion, $fromEdition);
- $changes = [];
- foreach($upgradeVersions as $openVersion => $chargedVersions)
- {
- if(version_compare($openVersion, $fromOpenVersion, '<')) continue;
- if(version_compare($openVersion, $toOpenVersion, '>=')) continue;
- $sqlFile = $this->upgrade->getUpgradeFile(str_replace('_', '.', $openVersion));
- $changes = array_merge($changes, $this->getChangesBySql($openVersion, $sqlFile));
- $changes = array_merge($changes, $this->getChangesByConfig($openVersion));
- foreach($chargedVersions as $chargedVersion)
- {
- foreach($chargedVersion as $version)
- {
- $sqlFile = $this->upgrade->getUpgradeFile(str_replace('_', '.', $version));
- $changes = array_merge($changes, $this->getChangesBySql($version, $sqlFile));
- $changes = array_merge($changes, $this->getChangesByConfig($version));
- }
- }
- }
- /* 如果此次升级到最终版本,则执行额外的数据处理流程。*/
- if(version_compare($toVersion, $this->config->version, '='))
- {
- $edition = $this->upgrade->getEditionByVersion($fromVersion);
- $methods = $this->upgrade->getOtherMethods($edition);
- foreach(array_keys($methods) as $method)
- {
- $changes[] = $this->getChangesByMethod($currentVersion, $method);
- }
- }
- return $changes;
- }
- /**
- * 获取配置文件中的变更内容列表。
- * Get changes by config.
- *
- * @param string $version
- * @access protected
- * @return array[]
- */
- protected function getChangesByConfig($version)
- {
- $changes = [];
- $functions = $this->config->upgrade->execFlow[$version]['functions'] ?? '';
- $xxsqls = $this->config->upgrade->execFlow[$version]['xxsqls'] ?? '';
- $xxfunctions = $this->config->upgrade->execFlow[$version]['xxfunctions'] ?? '';
- foreach(array_filter(explode(',', $functions)) as $function)
- {
- $changes[] = $this->getChangesByMethod($version, $function);
- }
- if($version == 'pro1_1_1')
- {
- $sqlFile = $this->upgrade->getUpgradeFile('pro1.1');
- $sqlChanges = $this->getChangesBySql($version, $sqlFile);
- $changes = array_merge($changes, $sqlChanges);
- }
- if($version == 'pro8_3')
- {
- $sqlFile = $this->ugprade->getUpgradeFile('pro8.2');
- $sqlChanges = $this->getChangesBySql($version, $sqlFile);
- $changes = array_merge($changes, $sqlChanges);
- }
- if(!empty($xxsqls))
- {
- foreach(array_filter(explode(',', $xxsqls)) as $sqlFile)
- {
- $sqlChanges = $this->getChangesBySql($version, $sqlFile);
- $changes = array_merge($changes, $sqlChanges);
- }
- }
- if(!empty($xxfunctions))
- {
- foreach(array_filter(explode(',', $xxfunctions)) as $function)
- {
- $changes[] = $this->getChangesByMethod($version, $function);
- }
- }
- return $changes;
- }
- /**
- * 获取 SQL 文件中的变更内容列表。
- * Get changes by sql file.
- *
- * @param string $version
- * @param string $sqlFile
- * @access protected
- * @return array[]
- */
- protected function getChangesBySql($version, $sqlFile)
- {
- if(!is_file($sqlFile)) return [];
- $changes = [];
- $sqls = $this->upgrade->parseToSqls($sqlFile);
- foreach($sqls as $sql)
- {
- $sqlMd5 = md5($sql);
- $fileMd5 = md5($sqlFile);
- if(isset($this->upgradeChanges[$version]['sqls'][$fileMd5][$sqlMd5])) continue;
- $this->upgradeChanges[$version]['sqls'][$fileMd5][$sqlMd5] = true;
- $items = $this->parseSqlToSemantic($sql);
- foreach($items as $item)
- {
- $search = ['%TABLE%', '%FIELD%', '%INDEX%', '%VIEW%', '%OLD%', '%NEW%'];
- $replace = [$item['table'] ?? '', $item['field'] ?? '', $item['index'] ?? '', $item['view'] ?? '', $item['old'] ?? '', $item['new'] ?? ''];
- $subject = $this->lang->upgrade->changeActions[$item['action']] ?? $this->lang->upgrade->changeActions['other'];
- $content = str_replace($search, $replace, $subject);
- $changes[] = ['version' => $version, 'type' => 'sql', 'mode' => $item['mode'], 'content' => $content, 'sql' => $sql, 'fileMd5' => $fileMd5, 'sqlMd5' => $sqlMd5];
- }
- }
- return $changes;
- }
- /**
- * 获取方法变更内容。
- * Get changes by method.
- *
- * @param string $version
- * @param string $rawMethod
- * @access protected
- * @return array
- */
- protected function getChangesByMethod($version, $rawMethod)
- {
- if(isset($this->upgradeChanges[$version]['methods'][$rawMethod])) return [];
- $this->upgradeChanges[$version]['methods'][$rawMethod] = true;
- $module = 'upgrade';
- $method = $rawMethod;
- if(strpos($rawMethod, '-') !== false)
- {
- list($module, $method) = explode('-', $rawMethod);
- }
- $content = str_replace(['%MODULE%', '%METHOD%'], [$module, $method], $this->lang->upgrade->changeActions['method']);
- return ['version' => $version, 'type' => 'method', 'mode' => 'update', 'content' => $content, 'method' => $rawMethod];
- }
- /**
- * 将 SQL 语句解析为语义化描述数组
- *
- * @param string $sql 单条 SQL 语句
- * @access protected
- * @return array[]
- */
- protected function parseSqlToSemantic($sql)
- {
- $sql = trim($sql);
- if($sql === '') return [];
- /* 移除末尾分号 */
- $sql = rtrim($sql, " \t\n\r;");
- if(preg_match('/^create\s+(or\s+replace\s+)?view\s+((?:`[^`]*`|\S)+)/i', $sql, $matches)) return [['mode' => 'create', 'action' => 'createView', 'view' => $this->extractTableName($matches[2])]]; // CREATE VIEW / CREATE OR REPLACE VIEW
- if(preg_match('/^drop\s+view\s+(if\s+exists\s+)?((?:`[^`]*`|\S)+)/i', $sql, $matches)) return [['mode' => 'delete', 'action' => 'dropView', 'view' => $this->extractTableName($matches[2])]]; // DROP VIEW
- if(preg_match('/^create\s+(unique\s+)?index\s+`?([\w]+)`?\s+on\s+((?:`[^`]*`|\S)+)/i', $sql, $matches)) return [['mode' => 'create', 'action' => 'addIndex', 'table' => $this->extractTableName($matches[3]), 'index' => $this->extractTableName($matches[2])]]; // CREATE INDEX idx ON table_name
- if(preg_match('/^drop\s+index\s+`?([\w]+)`?\s+on\s+((?:`[^`]*`|\S)+)/i', $sql, $matches)) return [['mode' => 'delete', 'action' => 'dropIndex', 'table' => $this->extractTableName($matches[2]), 'index' => $this->extractTableName($matches[1])]]; // DROP INDEX idx ON table_name
- if(preg_match('/^create\s+table\s+(if\s+not\s+exists\s+)?((?:`[^`]*`|\S)+)/i', $sql, $matches)) return [['mode' => 'create', 'action' => 'createTable', 'table' => $this->extractTableName($matches[2])]]; // CREATE TABLE
- if(preg_match('/^drop\s+table\s+(if\s+exists\s+)?((?:`[^`]*`|\S)+)/i', $sql, $matches)) return [['mode' => 'delete', 'action' => 'dropTable', 'table' => $this->extractTableName($matches[2])]]; // DROP TABLE
- if(preg_match('/^rename\s+table\s+((?:`[^`]*`|\S)+)\s+to\s+((?:`[^`]*`|\S)+)/i', $sql, $matches)) return [['mode' => 'update', 'action' => 'renameTable', 'old' => $this->extractTableName($matches[1]), 'new' => $this->extractTableName($matches[2])]]; // RENAME TABLE
- if(preg_match('/^(insert|replace)\s+into\s+((?:`[^`]*`|\S)+)/i', $sql, $matches)) return [['mode' => 'create', 'action' => 'insertValue', 'table' => $this->extractTableName($matches[2])]]; // INSERT / REPLACE
- if(preg_match('/^update\s+((?:`[^`]*`|\S)+)/i', $sql, $matches)) return [['mode' => 'update', 'action' => 'updateValue', 'table' => $this->extractTableName($matches[1])]]; // UPDATE
- if(preg_match('/^delete\s+from\s+((?:`[^`]*`|\S)+)/i', $sql, $matches)) return [['mode' => 'delete', 'action' => 'deleteValue', 'table' => $this->extractTableName($matches[1])]]; // DELETE
- /* ALTER TABLE */
- $sql = str_replace("\n", ' ', $sql); // 将换行替换为空格,方便后续处理
- if(preg_match('/^alter\s+table\s+((?:`[^`]*`|\S)+)\s+(.+)/i', $sql, $matches))
- {
- $tableName = $this->extractTableName($matches[1]);
- $alterBody = ltrim($matches[2]);
- /* 先检查是否是整表重命名:ALTER TABLE t RENAME TO new_t */
- if(preg_match('/^\s*rename\s+to\s+((?:`[^`]*`|\S)+)\s*$/i', $alterBody, $m)) return [['mode' => 'update', 'action' => 'renameTable', 'old' => $tableName, 'new' => trim($m[1], '`')]];
- $results = [];
- $clauses = $this->splitAlterClauses($alterBody);
- foreach($clauses as $clause)
- {
- $clause = trim($clause);
- if ($clause === '') continue;
- /* 提取关键词(忽略大小写) */
- $upperClause = preg_replace('/\s+/', ' ', strtoupper($clause));
- $words = explode(' ', $upperClause);
- if(empty($words)) continue;
- $first = $words[0];
- /* --- ADD [COLUMN/INDEX/KEY] --- */
- if($first === 'ADD')
- {
- /* 先尝试匹配 ADD INDEX / ADD KEY / ADD UNIQUE,再尝试匹配 ADD COLUMN 或 ADD field_name(即字段) */
- if(preg_match('/^add\s+(unique\s+)?(index|key)\s+(`[^`]*`|\w+)/i', $clause, $m))
- {
- $results[] = ['mode' => 'create', 'action' => 'addIndex', 'table' => $tableName, 'index' => trim($m[3], '`')];
- }
- else
- {
- /* 跳过 "COLUMN" */
- $pos = 1;
- if(isset($words[1]) && $words[1] === 'COLUMN') $pos = 2;
- /* 提取字段名(支持反引号,可能含空格) */
- if(isset($words[$pos]) && preg_match('/^add\s+(column\s+)?(`[^`]*`|\w+)/i', $clause, $m)) $results[] = ['mode' => 'create', 'action' => 'addField', 'table' => $tableName, 'field' => trim($m[2], '`')];
- }
- continue;
- }
- /* --- DROP [COLUMN/INDEX/KEY] --- */
- if($first === 'DROP')
- {
- if(isset($words[1]) && in_array($words[1], ['COLUMN', 'INDEX', 'KEY']))
- {
- /* 字段或索引 */
- if(preg_match('/^drop\s+(column|index|key)\s+(`[^`]*`|\w+)/i', $clause, $m))
- {
- $type = strtolower($m[1]);
- if($type === 'column')
- {
- $results[] = ['mode' => 'delete', 'action' => 'dropField', 'table' => $tableName, 'field' => trim($m[2], '`')];
- }
- else
- {
- $results[] = ['mode' => 'delete', 'action' => 'dropIndex', 'table' => $tableName, 'index' => trim($m[2], '`')];
- }
- }
- }
- else
- {
- /* 简写 DROP field_name */
- if(preg_match('/^drop\s+(`[^`]*`|\w+)/i', $clause, $m)) $results[] = ['mode' => 'delete', 'action' => 'dropField', 'table' => $tableName, 'field' => trim($m[1], '`')];
- }
- continue;
- }
- /* --- MODIFY [COLUMN] --- */
- if($first === 'MODIFY')
- {
- $pos = 1;
- if(isset($words[1]) && $words[1] === 'COLUMN') $pos = 2;
- if(isset($words[$pos]) && preg_match('/^modify\s+(column\s+)?(`[^`]*`|\w+)/i', $clause, $m)) $results[] = ['mode' => 'update', 'action' => 'modifyField', 'table' => $tableName, 'field' => trim($m[2], '`')];
- continue;
- }
- /* --- CHANGE [COLUMN] --- */
- if($first === 'CHANGE')
- {
- /* CHANGE [COLUMN] old_name new_name ... */
- $pos = 1;
- if(isset($words[1]) && $words[1] === 'COLUMN') $pos = 2;
- /* 使用原始子句提取两个标识符 */
- if(isset($words[$pos + 1]) && preg_match('/^change\s+(column\s+)?(`[^`]*`|\w+)\s+(`[^`]*`|\w+)/i', $clause, $m))
- {
- $old = trim($m[2], '`');
- $new = trim($m[3], '`');
- if($old == $new)
- {
- $results[] = ['mode' => 'update', 'action' => 'modifyField', 'table' => $tableName, 'field' => $old];
- }
- else
- {
- $results[] = ['mode' => 'update', 'action' => 'renameField', 'table' => $tableName, 'old' => $old, 'new' => $new];
- }
- }
- continue;
- }
- /* --- RENAME COLUMN old_name TO new_name (MySQL 8.0+) --- */
- if($first === 'RENAME' && isset($words[1]) && $words[1] === 'COLUMN' && preg_match('/^rename\s+column\s+(`[^`]*`|\w+)\s+to\s+(`[^`]*`|\w+)/i', $clause, $m)) $results[] = ['mode' => 'update', 'action' => 'renameField', 'table' => $tableName, 'old' => trim($m[1], '`'), 'new' => trim($m[2], '`')];
- }
- return $results;
- }
- return [];
- }
- /**
- * 从可能带数据库前缀的标识符中提取表名(如从 `db`.`table` 或 db.table 中提取 table)
- *
- * @param string $full 被反引号或不带反引号的标识符(如 "db.table" 或 "`my db`.`my-table`")
- * @access public
- * @return string 表名(不含反引号)
- */
- protected function extractTableName($full)
- {
- $full = trim($full); // 去除首尾空白
- // 截断第一个未被反引号包围的左括号之前的内容
- $trimmed = '';
- $inBacktick = false;
- for($i = 0; $i < strlen($full); $i++)
- {
- $c = $full[$i];
- if($c === '`')
- {
- $inBacktick = !$inBacktick;
- $trimmed .= $c;
- }
- elseif($c === '(' && !$inBacktick)
- {
- break; // 遇到未在反引号内的 '(',截断
- }
- else
- {
- $trimmed .= $c;
- }
- }
- $full = trim($trimmed);
- /* 按未被反引号包围的点分割 */
- $parts = [];
- $current = '';
- $inBacktick = false;
- for($i = 0; $i < strlen($full); $i++)
- {
- $c = $full[$i];
- if($c === '`')
- {
- $inBacktick = !$inBacktick;
- continue; // 反引号本身不存入
- }
- if($c === '.' && !$inBacktick)
- {
- $parts[] = $current;
- $current = '';
- }
- else
- {
- $current .= $c;
- }
- }
- $parts[] = $current;
- $tableName = end($parts); // 最后一个 part 就是表名
- return $tableName !== false ? $tableName : $full;
- }
- /**
- * 安全拆分 ALTER TABLE 子句,跳过字符串和括号内的逗号
- *
- * @param string $body
- * @access protected
- * @return string[]
- */
- protected function splitAlterClauses($body)
- {
- $clauses = [];
- $current = '';
- $len = strlen($body);
- $inSingle = false;
- $inDouble = false;
- $parenLevel = 0;
- for($i = 0; $i < $len; $i++)
- {
- $c = $body[$i];
- $next = ($i + 1 < $len) ? $body[$i + 1] : '';
- /* 处理转义(简化:跳过下一个字符) */
- if($c === '\\' && ($inSingle || $inDouble))
- {
- $current .= $c . $next;
- $i++;
- continue;
- }
- if($c === "'" && !$inDouble)
- {
- $inSingle = !$inSingle;
- }
- elseif($c === '"' && !$inSingle)
- {
- $inDouble = !$inDouble;
- }
- elseif($c === '(' && !$inSingle && !$inDouble)
- {
- $parenLevel++;
- }
- elseif($c === ')' && !$inSingle && !$inDouble)
- {
- $parenLevel--;
- }
- elseif($c === ',' && !$inSingle && !$inDouble && $parenLevel === 0)
- {
- $clauses[] = $current;
- $current = '';
- continue;
- }
- $current .= $c;
- }
- if($current !== '') $clauses[] = $current;
- return $clauses;
- }
- /**
- * 升级 sql 成功执行后的操作。
- * Operations after successful execution.
- *
- * @param string $fromVersion
- * @access protected
- * @return string
- */
- protected function getRedirectUrlAfterExecute($fromVersion)
- {
- /* Delete all patch actions if upgrade success. */
- $this->loadModel('action')->deleteByType('patch');
- $selectMode = true;
- $systemMode = $this->loadModel('setting')->getItem('owner=system&module=common§ion=global&key=mode');
- /* 如果经典管理模式。*/
- /* If the system mode is classic. */
- if($systemMode == 'classic' && $this->config->edition != 'ipd')
- {
- $this->upgradeFromClassicMode();
- $selectMode = false;
- }
- /* 从15 版本以后升级。*/
- /* when upgrade from the vesion is more than 15. */
- $rawFromVersion = $fromVersion;
- if(strpos($rawFromVersion, 'lite') !== false) $rawFromVersion = $this->config->upgrade->liteVersion[$fromVersion];
- $openVersion = $this->upgrade->getOpenVersion($rawFromVersion);
- if(version_compare($openVersion, '15_0_rc1', '>=') && $systemMode == 'new')
- {
- $this->setting->setItem('system.common.global.mode', 'ALM');
- $selectMode = false;
- }
- if(version_compare($openVersion, '18_0_beta1', '>=')) $selectMode = false;
- /* 如果是 ipd 版本,设置相关的配置。*/
- /* When the edition is ipd. */
- if($this->config->edition == 'ipd') $this->setIpdItems($openVersion);
- $this->setting->setItem('system.common.userview.relatedTablesUpdateTime', time());
- if($selectMode)
- {
- if($this->config->edition == 'ipd') return inlink('to18Guide', "fromVersion={$fromVersion}&mode=ALM");
- return inlink('to18Guide', "fromVersion={$fromVersion}");
- }
- return inlink('afterExec', "fromVersion={$fromVersion}");
- }
- /**
- * 从经典模式升级后的处理。
- * Process after upgrade from classic mode.
- *
- * @access private
- * @return void
- */
- private function upgradeFromClassicMode()
- {
- $this->loadModel('setting')->setItem('system.common.global.mode', 'light');
- $programID = $this->setDefaultProgram();
- $_POST['projectType'] = 'execution';
- $this->upgrade->upgradeInProjectMode($programID, 'classic');
- $this->upgrade->computeObjectMembers();
- $this->upgrade->initUserView();
- $this->upgrade->setDefaultPriv();
- $this->dao->update(TABLE_CONFIG)->set('value')->eq('0_0')->where('`key`')->eq('productProject')->exec();
- $hourPoint = $this->setting->getItem('owner=system&module=custom&key=hourPoint');
- if(empty($hourPoint)) $this->setting->setItem('system.custom.hourPoint', 0);
- $sprints = $this->dao->select('id')->from(TABLE_PROJECT)->where('type')->eq('sprint')->fetchAll('id');
- $this->dao->update(TABLE_ACTION)->set('objectType')->eq('execution')->where('objectID')->in(array_keys($sprints))->andWhere('objectType')->eq('project')->exec();
- $this->loadModel('custom')->disableFeaturesByMode('light');
- }
- /**
- * Ipd 版本升级后的处理。
- * Set ipd items.
- *
- * @param string $openVersion
- * @access private
- * @return void
- */
- private function setIpdItems($openVersion = '')
- {
- $this->loadModel('setting')->setItem('system.common.global.mode', 'PLM');
- $this->setting->setItem('system.custom.URAndSR', '1');
- $this->upgrade->addORPriv($openVersion);
- }
- /**
- * 设置迭代的概念。
- * Set sprint concept.
- *
- * @access protected
- * @return void
- */
- protected function setSprintConcept()
- {
- $sprintConcept = 0;
- if(isset($this->config->custom->sprintConcept))
- {
- if($this->config->custom->sprintConcept == 2) $sprintConcept = 1;
- }
- elseif(isset($this->config->custom->productProject))
- {
- $projectConcept = substr($this->config->custom->productProject, strpos($this->config->custom->productProject, '_'));
- if($projectConcept == 2) $sprintConcept = 1;
- }
- $this->loadModel('setting')->setItem('system.custom.sprintConcept', $sprintConcept);
- }
- /**
- * 创建默认项目集,并且将项目关联到默认项目集。
- * Set default program.
- *
- * @access protected
- * @return int
- */
- protected function setDefaultProgram()
- {
- $programID = $this->loadModel('program')->createDefaultProgram();
- $this->loadModel('setting')->setItem('system.common.global.defaultProgram', $programID);
- /* Set default program for product and project with no program. */
- $this->upgrade->relateDefaultProgram($programID);
- return $programID;
- }
- /**
- * 合并后的升级操作。
- * Upgrade after merged.
- *
- * @access protected
- * @return void
- */
- protected function upgradeAfterMerged()
- {
- $this->upgrade->computeObjectMembers();
- $this->upgrade->initUserView();
- $this->upgrade->setDefaultPriv();
- $this->dao->update(TABLE_CONFIG)->set('value')->eq('0_0')->where('`key`')->eq('productProject')->exec();
- /* Set defult hourPoint. */
- $hourPoint = $this->loadModel('setting')->getItem('owner=system&module=custom&key=hourPoint');
- if(empty($hourPoint)) $this->setting->setItem('system.custom.hourPoint', 0);
- /* Update sprints history. */
- $sprints = $this->dao->select('id')->from(TABLE_PROJECT)->where('type')->eq('sprint')->fetchAll('id');
- $this->dao->update(TABLE_ACTION)->set('objectType')->eq('execution')->where('objectID')->in(array_keys($sprints))->andWhere('objectType')->eq('project')->exec();
- $this->locate($this->createLink('upgrade', 'mergeRepo'));
- }
- /**
- * 获取产品线下的产品和项目。
- * Get products and projects group by product line.
- *
- * @param string $projectType
- * @access protected
- * @return void
- */
- protected function assignProductsAndProjectsGroupByProductline($projectType)
- {
- $productlines = $this->dao->select('*')->from(TABLE_MODULE)->where('type')->eq('line')->andWhere('root')->eq(0)->orderBy('id_desc')->fetchAll('id');
- $noMergedProducts = $this->dao->select('*')->from(TABLE_PRODUCT)->where('line')->in(array_keys($productlines))->andWhere('vision')->eq('rnd')->orderBy('id_desc')->fetchAll('id');
- if(empty($productlines) || empty($noMergedProducts)) $this->locate($this->createLink('upgrade', 'mergeProgram', "type=product&programID=0&projectType=$projectType"));
- /* Group product by product line. */
- $lineGroups = array();
- foreach($noMergedProducts as $product) $lineGroups[$product->line][$product->id] = $product;
- foreach($productlines as $line)
- {
- if(!isset($lineGroups[$line->id])) unset($productlines[$line->id]);
- }
- $noMergedSprints = $this->dao->select('t1.*')->from(TABLE_PROJECT)->alias('t1')
- ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id=t2.project')
- ->where('t1.project')->eq(0)
- ->andWhere('t1.deleted')->eq(0)
- ->andWhere('t1.vision')->eq('rnd')
- ->andWhere('t1.type')->eq('sprint')
- ->andWhere('t2.product')->in(array_keys($noMergedProducts))
- ->orderBy('t1.id_desc')
- ->fetchAll('id');
- /* Remove sprint that linked more than two products */
- $sprintProducts = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)->where('project')->in(array_keys($noMergedSprints))->fetchGroup('project', 'product');
- foreach($sprintProducts as $sprintID => $products)
- {
- if(count($products) > 1) unset($noMergedSprints[$sprintID]);
- }
- /* Group sprint by product. */
- $productGroups = array();
- foreach($noMergedSprints as $sprint)
- {
- $sprintProduct = zget($sprintProducts, $sprint->id, array());
- if(empty($sprintProduct)) continue;
- $productID = key($sprintProduct);
- $productGroups[$productID][$sprint->id] = $sprint;
- }
- $this->view->productlines = $productlines;
- $this->view->lineGroups = $lineGroups;
- $this->view->productGroups = $productGroups;
- }
- /**
- * 获取产品下的项目。
- * Get projects group by product.
- *
- * @param string $projectType
- * @access protected
- * @return void
- */
- protected function assignProjectsGroupByProduct($projectType)
- {
- $noMergedSprints = $this->dao->select('t2.*')->from(TABLE_PROJECTPRODUCT)->alias('t1')
- ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
- ->where('t2.model')->eq('')
- ->andWhere('t2.project')->eq(0)
- ->andWhere('t2.vision')->eq('rnd')
- ->andWhere('t2.deleted')->eq(0)
- ->andWhere('t2.type')->eq('sprint')
- ->fetchAll('id');
- /* Remove project that linked more than two products */
- $sprintProducts = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)->where('project')->in(array_keys($noMergedSprints))->fetchGroup('project', 'product');
- foreach($sprintProducts as $sprintID => $products)
- {
- if(count($products) > 1) unset($noMergedSprints[$sprintID]);
- }
- /* Get products that are not merged by sprints. */
- $noMergedProducts = array();
- if($noMergedSprints)
- {
- $noMergedProducts = $this->dao->select('t1.*')->from(TABLE_PRODUCT)->alias('t1')
- ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id=t2.product')
- ->where('t2.project')->in(array_keys($noMergedSprints))
- ->andWhere('t1.vision')->eq('rnd')
- ->fetchAll('id');
- }
- /* Add products without sprints. */
- $noMergedProducts += $this->dao->select('*')->from(TABLE_PRODUCT)->where('program')->eq(0)->andWhere('vision')->eq('rnd')->fetchAll('id');
- if(empty($noMergedProducts)) $this->locate($this->createLink('upgrade', 'mergeProgram', "type=sprint&programID=0&projectType=$projectType"));
- /* Group project by product. */
- $productGroups = array();
- foreach($noMergedSprints as $sprint)
- {
- $sprintProduct = zget($sprintProducts, $sprint->id, array());
- if(empty($sprintProduct)) continue;
- $productID = key($sprintProduct);
- $productGroups[$productID][$sprint->id] = $sprint;
- }
- $this->view->noMergedProducts = $noMergedProducts;
- $this->view->productGroups = $productGroups;
- }
- /**
- * 获取未关联产品的迭代。
- * Get sprints without product.
- *
- * @access protected
- * @return void
- */
- protected function assignSprintsWithoutProduct()
- {
- $noMergedSprints = $this->dao->select('*')->from(TABLE_PROJECT)
- ->where('project')->eq(0)
- ->andWhere('vision')->eq('rnd')
- ->andWhere('type')->eq('sprint')
- ->andWhere('deleted')->eq(0)
- ->orderBy('id_desc')
- ->fetchAll('id');
- $projectProducts = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)->where('project')->in(array_keys($noMergedSprints))->fetchGroup('project', 'product');
- foreach(array_keys($projectProducts) as $sprintID) unset($noMergedSprints[$sprintID]);
- if(empty($noMergedSprints)) $this->locate($this->createLink('upgrade', 'mergeProgram', "type=moreLink"));
- $this->view->noMergedSprints = $noMergedSprints;
- }
- /**
- * 获取关联了多个产品项目。
- * Get no merged projects that link more than two products.
- *
- * @access protected
- * @return void
- */
- protected function assignSprintsWithMoreProducts()
- {
- $noMergedSprints = $this->dao->select('*')->from(TABLE_PROJECT)
- ->where('project')->eq(0)
- ->andWhere('vision')->eq('rnd')
- ->andWhere('type')->eq('sprint')
- ->andWhere('deleted')->eq(0)
- ->orderBy('id_desc')
- ->fetchAll('id');
- $projectProducts = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)->where('project')->in(array_keys($noMergedSprints))->fetchGroup('project', 'product');
- $productPairs = array();
- foreach($projectProducts as $sprintID => $products)
- {
- foreach(array_keys($products) as $productID) $productPairs[$productID] = $productID;
- }
- $projects = $this->dao->select('t1.*, t2.product AS productID')->from(TABLE_PROJECT)->alias('t1')
- ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id=t2.project')
- ->where('t2.product')->in($productPairs)
- ->andWhere('t1.vision')->eq('rnd')
- ->andWhere('t1.type')->eq('project')
- ->fetchAll('productID');
- foreach($noMergedSprints as $sprintID => $sprint)
- {
- $products = zget($projectProducts, $sprintID, array());
- foreach(array_keys($products) as $productID)
- {
- $project = zget($projects, $productID, '');
- if($project) $sprint->projects[$project->id] = $project->name;
- }
- if(!isset($sprint->projects)) $sprint->projects = $this->dao->select('id,name')->from(TABLE_PROJECT)->where('type')->eq('project')->andWhere('vision')->eq('rnd')->fetchPairs();
- }
- $this->view->noMergedSprints = $noMergedSprints;
- }
- /**
- * 合并按产品线分组的产品和迭代。
- * Merge products and projects group by productline.
- *
- * @param string $projectType
- * @access protected
- * @return void
- */
- protected function mergeByProductline($projectType)
- {
- /* Compute checked products and sprints, unchecked products and sprints. */
- $linkedProducts = array();
- $linkedSprints = array();
- $unlinkSprints = array();
- $sprintProducts = array();
- foreach($_POST['products'] as $lineID => $products)
- {
- foreach($products as $productID)
- {
- $linkedProducts[$productID] = $productID;
- if(!isset($_POST['sprints'][$lineID][$productID])) continue;
- foreach($_POST['sprints'][$lineID][$productID] as $sprintID)
- {
- $linkedSprints[$sprintID] = $sprintID;
- $sprintProducts[$sprintID] = $productID;
- unset($_POST['sprintIdList'][$lineID][$productID][$sprintID]);
- }
- $unlinkSprints[$productID] = $this->post->sprintIdList[$lineID][$productID];
- }
- }
- /* Create Program. */
- $result = $this->upgrade->createProgram($linkedSprints);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- if(isset($result['result']) && $result['result'] == 'fail') return $this->send($result);
- list($programID, $projectList, $lineID) = $result;
- /* Process merged products and projects. */
- if($projectType == 'execution')
- {
- /* Use historical projects as execution upgrades. */
- $this->upgrade->processMergedData($programID, $projectList, $lineID, $linkedProducts, $linkedSprints);
- }
- else
- {
- /* Use historical projects as project upgrades. */
- foreach($linkedSprints as $sprint) $this->upgrade->processMergedData($programID, zget($projectList, $sprint, array()), $lineID, array($sprintProducts[$sprint] => $sprintProducts[$sprint]), array($sprint => $sprint));
- /* When upgrading historical data as a project, handle products that are not linked with the project. */
- $singleProducts = array_diff($linkedProducts, $sprintProducts);
- if(!empty($singleProducts)) $this->upgrade->computeProductAcl($singleProducts, $programID, $lineID);
- }
- /* Process unlinked sprint and product. */
- foreach(array_keys($linkedProducts) as $productID)
- {
- if((isset($unlinkSprints[$productID]) && empty($unlinkSprints[$productID])) || !isset($unlinkSprints[$productID])) $this->dao->update(TABLE_PRODUCT)->set('line')->eq($lineID)->where('id')->eq($productID)->exec();
- }
- }
- /**
- * 合并按产品分组的产品和迭代。
- * Merge products and projects group by product.
- *
- * @param string $projectType
- * @access protected
- * @return void
- */
- protected function mergeByProduct($projectType)
- {
- $linkedProducts = array();
- $linkedSprints = array();
- $unlinkSprints = array();
- $sprintProducts = array();
- foreach($_POST['products'] as $productID)
- {
- $linkedProducts[$productID] = $productID;
- if(isset($_POST['sprints'][$productID]))
- {
- foreach($_POST['sprints'][$productID] as $sprintID)
- {
- $linkedSprints[$sprintID] = $sprintID;
- $sprintProducts[$sprintID] = $productID;
- unset($_POST['sprintIdList'][$productID][$sprintID]);
- }
- $unlinkSprints += $this->post->sprintIdList[$productID];
- }
- }
- /* Create Program. */
- $result = $this->upgrade->createProgram($linkedSprints);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- if(isset($result['result']) && $result['result'] == 'fail') return $this->send($result);
- list($programID, $projectList, $lineID) = $result;
- /* Process productline. */
- $this->dao->delete()->from(TABLE_MODULE)->where('`root`')->eq(0)->andWhere('`type`')->eq('line')->exec();
- /* Process merged products and projects. */
- if($projectType == 'execution')
- {
- /* Use historical projects as execution upgrades. */
- $this->upgrade->processMergedData($programID, $projectList, $lineID, $linkedProducts, $linkedSprints);
- }
- else
- {
- /* Use historical projects as project upgrades. */
- foreach($linkedSprints as $sprint) $this->upgrade->processMergedData($programID, $projectList[$sprint], $lineID, array($sprintProducts[$sprint] => $sprintProducts[$sprint]), array($sprint => $sprint));
- /* When upgrading historical data as a project, handle products that are not linked with the project. */
- $singleProducts = array_diff($linkedProducts, $sprintProducts);
- if(!empty($singleProducts)) $this->upgrade->computeProductAcl($singleProducts, $programID, $lineID);
- }
- }
- /**
- * 合并没有关联产品的迭代。
- * Merge sprints without product.
- *
- * @param string $projectType
- * @access protected
- * @return void
- */
- protected function mergeBySprint($projectType)
- {
- $linkedSprints = $this->post->sprints;
- /* Create Program. */
- $result = $this->upgrade->createProgram($linkedSprints);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- if(isset($result['result']) && $result['result'] == 'fail') return $this->send($result);
- list($programID, $projectList, $lineID) = $result;
- if($projectType == 'execution')
- {
- /* Use historical projects as execution upgrades. */
- $this->upgrade->processMergedData($programID, $projectList, $lineID, array(), $linkedSprints);
- }
- else
- {
- /* Use historical projects as project upgrades. */
- foreach($linkedSprints as $sprint) $this->upgrade->processMergedData($programID, $projectList[$sprint], $lineID, array(), array($sprint => $sprint));
- }
- }
- /**
- * 合并关联多个产品的迭代。
- * Merge sprints with more than one product.
- *
- * @param string $projectType
- * @access protected
- * @return void
- */
- protected function mergeByMoreLink($projectType)
- {
- $linkedSprints = $this->post->sprints;
- /* Create Program. */
- list($programID, $projectList, $lineID) = $this->upgrade->createProgram($linkedSprints);
- if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
- if($projectType == 'execution')
- {
- /* Use historical projects as execution upgrades. */
- $this->upgrade->processMergedData($programID, $projectList, $lineID, array(), $linkedSprints);
- }
- else
- {
- /* Use historical projects as project upgrades. */
- foreach($linkedSprints as $sprint) $this->upgrade->processMergedData($programID, $projectList[$sprint], $lineID, array(), array($sprint => $sprint));
- }
- /* If is more-link sprints, and as project upgrade, set old relation into new project. */
- $projectProducts = $this->dao->select('product,project,branch,plan')->from(TABLE_PROJECTPRODUCT)->where('project')->in($linkedSprints)->fetchAll();
- foreach($projectProducts as $projectProduct)
- {
- $data = new stdclass();
- $data->project = $projectType == 'execution' ? $projectList : $projectList[$projectProduct->project];
- $data->product = $projectProduct->product;
- $data->plan = $projectProduct->plan;
- $data->branch = $projectProduct->branch;
- $this->dao->replace(TABLE_PROJECTPRODUCT)->data($data)->exec();
- }
- }
- /**
- * 显示更改冲突的 sql。
- * Display consistency.
- *
- * @param string $alterSQL
- * @access protected
- * @return void
- */
- protected function displayConsistency($alterSQL)
- {
- $logFile = $this->upgrade->getConsistencyLogFile();
- if(file_exists($logFile)) unlink($logFile);
- $this->view->title = $this->lang->upgrade->consistency;
- $this->view->hasError = $this->upgrade->hasConsistencyError();
- $this->view->alterSQL = $alterSQL;
- $this->view->version = $this->config->version;
- $this->display('upgrade', 'consistency');
- }
- /**
- * 显示需要执行的命令。
- * Display command.
- *
- * @param string $command
- * @param string $tips
- * @access protected
- * @return void
- */
- protected function displayCommand($command, $tips = '')
- {
- $this->view->title = $this->lang->upgrade->common;
- $this->view->result = 'fail';
- $this->view->command = $command;
- $this->view->tips = $tips ?: $this->lang->upgrade->execCommand;
- $this->display('upgrade', 'command');
- }
- /**
- * 显示待处理的提示。
- * Display execute process.
- *
- * @param string $fromVersion
- * @param array $needProcess
- * @access protected
- * @return void
- */
- protected function displayExecuteProcess($fromVersion, $needProcess)
- {
- $showPrivTips = false;
- if(is_numeric($fromVersion[0]) and version_compare($fromVersion, '18.9', '<=')) $showPrivTips = true;
- if(strpos($fromVersion, 'pro') !== false) $showPrivTips = true;
- if(strpos($fromVersion, 'biz') !== false and version_compare($fromVersion, 'biz8.9', '<=')) $showPrivTips = true;
- if(strpos($fromVersion, 'max') !== false and version_compare($fromVersion, 'max4.9', '<=')) $showPrivTips = true;
- if(strpos($fromVersion, 'ipd') !== false and version_compare($fromVersion, 'ipd1.1.1', '<=')) $showPrivTips = true;
- if($showPrivTips and $this->config->edition == 'open') $showPrivTips = false;
- $this->view->title = $this->lang->upgrade->result;
- $this->view->needProcess = $needProcess;
- $this->view->fromVersion = $fromVersion;
- $this->view->showPrivTips = $showPrivTips;
- $this->display();
- }
- /**
- * 升级 sql 执行成功后的操作。
- * Process after execute sql successfully.
- *
- * @access protected
- * @return void
- */
- protected function processAfterExecSuccessfully()
- {
- $zfile = $this->app->loadClass('zfile');
- $zfile->removeDir($this->app->getTmpRoot() . 'model/');
- $installFile = $this->app->getAppRoot() . 'www/install.php';
- $upgradeFile = $this->app->getAppRoot() . 'www/upgrade.php';
- if(file_exists($installFile)) @unlink($installFile);
- if(file_exists($upgradeFile)) @unlink($upgradeFile);
- unset($_SESSION['upgrading']);
- }
- }
|