PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/upload/src/applications/appcenter/service/srv/do/PwInstall.php

https://gitlab.com/wuhang2003/phpwind
PHP | 428 lines | 310 code | 20 blank | 98 comment | 57 complexity | 0a442725922bebd5527462df7f121782 MD5 | raw file
  1. <?php
  2. Wind::import('APPCENTER:service.srv.iPwInstall');
  3. Wind::import('APPCENTER:service.dm.PwApplicationDm');
  4. Wind::import('APPCENTER:service.srv.helper.PwSystemHelper');
  5. /**
  6. *
  7. * @author Qiong Wu <papa0924@gmail.com>
  8. * @copyright ©2003-2103 phpwind.com
  9. * @license http://www.windframework.com
  10. * @version $Id: PwInstall.php 24585 2013-02-01 04:02:37Z jieyin $
  11. * @package wind
  12. */
  13. class PwInstall implements iPwInstall {
  14. const TARGET = 'EXT:';
  15. const DB_TABLE = 'conf/data.sql';
  16. const CONTROLLER = 'controller/IndexController.php';
  17. const ADMIN = 'admin/ManageController.php';
  18. /*
  19. * (non-PHPdoc) @see iPwInstall::unInstall()
  20. */
  21. public function unInstall($uninstall) {
  22. if ($table = $uninstall->getInstallLog('table')) {
  23. try {
  24. /* @var $db WindConnection */
  25. $db = Wind::getComponent('db');
  26. foreach ($table as $key => $value) {
  27. $db->execute('DROP TABLE IF EXISTS `' . $key . '`');
  28. }
  29. } catch (Exception $e) {}
  30. }
  31. if ($inject = $uninstall->getInstallLog('inject')) $this->_loadPwHookInject()->batchDel(
  32. $inject);
  33. if ($hooks = $uninstall->getInstallLog('hook')) $this->_loadPwHooks()->batchDelByName(
  34. $hooks);
  35. if ($appId = $uninstall->getInstallLog('appId')) $this->_load()->delByAppId($appId);
  36. if ($packs = $uninstall->getInstallLog('packs')) {
  37. /*
  38. * foreach ($packs as $value) { if (is_dir($value))
  39. * WindFolder::rm($value, true); if (is_file($value))
  40. * WindFile::del($value); }
  41. */
  42. }
  43. return true;
  44. }
  45. /*
  46. * (non-PHPdoc) @see iPwInstall::install()
  47. */
  48. public function install($install) {
  49. $manifest = $install->getManifest();
  50. $appId = $install->getAppId();
  51. $result = $this->_load()->findByAppId($appId);
  52. if ($result instanceof PwError) return $result;
  53. if ($result) return new PwError('APPCENTER:install.exist.fail', array('{{error}}' => $appId));
  54. $alias = $manifest->getApplication('alias');
  55. if (!$alias) return new PwError('APPCENTER:install.fail.alias.empty');
  56. /*
  57. * if (!preg_match('/^[a-z][a-z0-9]+$/i', $alias)) return new
  58. * PwError('APPCENTER:illegal.alias');
  59. */
  60. $result = $this->_load()->findByAlias($alias);
  61. if ($result instanceof PwError) return $result;
  62. if ($result) return new PwError('APPCENTER:install.exist.fail', array('{{error}}' => $alias));
  63. $hooks = $manifest->getHooks();
  64. if ($hooks) {
  65. $result = $this->_loadPwHooks()->batchFetchByName(array_keys($hooks));
  66. if ($result) {
  67. return new PwError('HOOK:hook.exit',
  68. array('{{error}}' => implode(',', array_keys($result))));
  69. }
  70. }
  71. $inject = $manifest->getInjectServices();
  72. if ($inject) {
  73. $hookNames = array();
  74. foreach ($inject as $value) {
  75. if (array_key_exists($value['hook_name'], $hooks)) continue;
  76. $hookNames[] = $value['hook_name'];
  77. }
  78. if ($hookNames) {
  79. $hook = $this->_loadPwHooks()->batchFetchByName(array_unique($hookNames));
  80. $result = $this->_loadPwHookInject()->fetchByHookName(array_unique($hookNames));
  81. if ($result) {
  82. $injects = array();
  83. foreach ($result as $v) {
  84. $injects[$v['hook_name']][] = $v['alias'];
  85. }
  86. foreach ($inject as $key => $value) {
  87. $_hookName = $value['hook_name'];
  88. if (isset($injects[$_hookName]) && in_array($value['alias'], $injects[$_hookName])) {
  89. return new PwError('HOOK:inject.exit', array('{{error}}' => $value['alias']));
  90. }
  91. }
  92. }
  93. }
  94. }
  95. file_put_contents(DATA_PATH . 'tmp/log', 'checkinstall!', FILE_APPEND);
  96. return true;
  97. }
  98. /*
  99. * (non-PHPdoc) @see iPwInstall::backUp()
  100. */
  101. public function backUp($upgrade) {
  102. /* @var $upgrade PwUpgradeApplication */
  103. if ($table = $upgrade->getBackLog('table')) {
  104. $upgrade->setRevertLog('table', $table);
  105. // 更新时不动原先数据
  106. /*
  107. * try { $db = Wind::getComponent('db'); foreach ($table as $key =>
  108. * $value) { $db->execute('DROP TABLE IF EXISTS `' . $key . '`'); }
  109. * } catch (Exception $e) {}
  110. */
  111. }
  112. if ($inject = $upgrade->getBackLog('inject')) {
  113. $upgrade->setRevertLog('inject', $this->_loadPwHookInject()->fetch($inject));
  114. $this->_loadPwHookInject()->batchDel($inject);
  115. }
  116. if ($hooks = $upgrade->getBackLog('hook')) {
  117. $upgrade->setRevertLog('hook', $this->_loadPwHooks()->batchFetchByName($hooks));
  118. $this->_loadPwHooks()->batchDelByName($hooks);
  119. }
  120. if ($appId = $upgrade->getBackLog('appId')) {
  121. $upgrade->setRevertLog('appId', $this->_load()->findByAppId($appId));
  122. $this->_load()->delByAppId($appId);
  123. }
  124. if ($packs = $upgrade->getBackLog('packs')) {
  125. $targetDir = $upgrade->getTmpPath() . '/bak/';
  126. $log = array();
  127. foreach ($packs as $k => $value) {
  128. $target = $upgrade->getTmpPath() . '/' . basename($value) . '_' . $k . '.bak';
  129. PwApplicationHelper::mvSourcePack($value, $target);
  130. $log[] = array($value, $target);
  131. }
  132. $upgrade->setRevertLog('packs', $log);
  133. }
  134. return true;
  135. }
  136. /*
  137. * (non-PHPdoc) @see iPwInstall::revert()
  138. */
  139. public function revert($upgrade) {
  140. /* @var $upgrade PwUpgradeApplication */
  141. if ($table = $upgrade->getRevertLog('table')) {
  142. // 更新时不动原先数据
  143. /*
  144. * try { $db = Wind::getComponent('db'); foreach ($table as $key =>
  145. * $value) { $db->execute($value); } } catch (Exception $e) {}
  146. */
  147. }
  148. if ($inject = $upgrade->getRevertLog('inject')) {
  149. $this->_loadPwHookInject()->batchAdd($inject);
  150. }
  151. if ($hooks = $upgrade->getRevertLog('hook')) {
  152. $this->_loadPwHooks()->batchAdd($hooks);
  153. }
  154. if ($app = $upgrade->getRevertLog('appId')) {
  155. $dm = new PwApplicationDm();
  156. $dm->setAppId($app['app_id']);
  157. $dm->setName($app['name']);
  158. $dm->setAlias($app['alias']);
  159. $dm->setVersion($app['version']);
  160. $dm->setPwVersion($app['pw_version']);
  161. $dm->setDescription($app['description']);
  162. $dm->setLogo($app['logo']);
  163. $dm->setAuthorName($app['author_name']);
  164. $dm->setAuthorEmail($app['author_email']);
  165. $dm->setAuthorIcon($app['author_icon']);
  166. $dm->setCreatedTime($app['created_time']);
  167. $dm->setModifiedTime($app['modified_time']);
  168. $this->_load()->add($dm);
  169. }
  170. if ($packs = $upgrade->getRevertLog('packs')) {
  171. foreach ($packs as $value) {
  172. PwApplicationHelper::mvSourcePack($value[1], $value[0]);
  173. }
  174. }
  175. return true;
  176. }
  177. /**
  178. *
  179. * @see iPwInstall::afterInstall()
  180. * @param PwInstallApplication $install
  181. */
  182. public function afterInstall($install) {
  183. if ($install->getTmpPackage()) {
  184. $r = $this->registeResource($install);
  185. if ($r instanceof PwError) return $r;
  186. $name = $install->getManifest()->getApplication('alias');
  187. $writable = PwSystemHelper::checkWriteAble(EXT_PATH . $name . '/');
  188. if (!$writable) return new PwError('APPCENTER:install.mv.fail',
  189. array('{{error}}' => 'EXT:' . $name));
  190. $targetPath = EXT_PATH . $name;
  191. PwApplicationHelper::mvSourcePack($install->getTmpPackage(), $targetPath);
  192. $install->addInstallLog('packs', $targetPath);
  193. }
  194. file_put_contents(DATA_PATH . 'tmp/log', 'afterinstall!', FILE_APPEND);
  195. return true;
  196. }
  197. /**
  198. *
  199. * @see iPwInstall::rollback()
  200. * @param PwInstallApplication $install
  201. */
  202. public function rollback($install) {
  203. if ($appId = $install->getInstallLog('appId')) $this->_load()->delByAppId($appId);
  204. if ($hooks = $install->getInstallLog('hook')) $this->_loadPwHooks()->batchDelByName($hooks);
  205. if ($inject = $install->getInstallLog('inject')) $this->_loadPwHookInject()->batchDel(
  206. $inject);
  207. if ($table = $install->getInstallLog('table')) {
  208. try {
  209. /* @var $db WindConnection */
  210. $db = Wind::getComponent('db');
  211. foreach ($table as $value) {
  212. $db->execute('DROP TABLE IF EXISTS `' . $value . '`');
  213. }
  214. } catch (Exception $e) {}
  215. }
  216. return true;
  217. }
  218. /**
  219. * 注册数据文件
  220. *
  221. * @param PwInstallApplication $install
  222. * @return PwError true
  223. */
  224. public function registeData($install) {
  225. try {
  226. $sqlFile = $install->getTmpPackage() . '/' . self::DB_TABLE;
  227. if (!is_file($sqlFile)) return true;
  228. $strSql = WindFile::read($sqlFile);
  229. /* @var $db WindConnection */
  230. $db = Wind::getComponent('db');
  231. $sql = PwApplicationHelper::sqlParser($strSql, $db->getConfig('charset', '', 'utf8'),
  232. $db->getTablePrefix(), $db->getConfig('engine', '', 'MYISAM'));
  233. if ($sql['CREATE']) {
  234. foreach ($sql['CREATE'] as $table => $statement) {
  235. $db->execute($statement);
  236. }
  237. }
  238. $install->setInstallLog('table', $sql['CREATE']);
  239. foreach ($sql as $option => $statements) {
  240. if (!in_array($option, array('INSERT', 'UPDATE', 'REPLACE', 'ALTER'))) continue;
  241. foreach ($statements as $table => $statement) {
  242. if ($option == 'ALTER') {
  243. if (preg_match(
  244. '/^ALTER\s+TABLE\s+`?(\w+)`?\s+(DROP|ADD)\s+(KEY|INDEX|UNIQUE)\s+([\w\(\),`]+)?/i',
  245. $statement, $matches)) {
  246. list($key, $fields) = explode('(', $matches[4]);
  247. $fields = trim($fields, '),');
  248. list($matches[3]) = explode(' ', $matches[3]);
  249. $matches[3] = trim(strtoupper($matches[3]));
  250. PwSystemHelper::alterIndex(
  251. array(
  252. $matches[1],
  253. $key,
  254. $fields ? $fields : '',
  255. $matches[3],
  256. $matches[2]), $db);
  257. } elseif (preg_match(
  258. '/^ALTER\s+TABLE\s+`?(\w+)`?\s+(CHANGE|DROP|ADD)\s+`?(\w+)`?/i',
  259. $statement, $matches)) {
  260. PwSystemHelper::alterField(array($matches[1], $matches[3], $statement),
  261. $db);
  262. } else {
  263. $db->execute($statement);
  264. }
  265. } else {
  266. if ($option == 'INSERT') {
  267. $statement = 'REPLACE' . substr($statement, 6);
  268. }
  269. $db->execute($statement);
  270. }
  271. }
  272. }
  273. return true;
  274. } catch (Exception $e) {
  275. return new PwError('APPCENTER:install.fail', array('{{error}}' => $e->getMessage()));
  276. }
  277. file_put_contents(DATA_PATH . 'tmp/log', 'registedata!', FILE_APPEND);
  278. }
  279. /**
  280. * 注册钩子信息
  281. *
  282. * @param PwInstallApplication $install
  283. * @return PwError true
  284. */
  285. public function registeHooks($install) {
  286. $manifest = $install->getManifest();
  287. $hooks = $manifest->getHooks();
  288. if (!$hooks) return true;
  289. foreach ($hooks as $key => $hook) {
  290. $hook['app_id'] = $install->getAppId();
  291. $hook['app_name'] = $install->getManifest()->getApplication('name');
  292. $hooks[$key] = $hook;
  293. }
  294. $this->_loadPwHooks()->batchAdd($hooks);
  295. $install->setInstallLog('hook', array_keys($hooks));
  296. return true;
  297. }
  298. /**
  299. * 注册注入服务
  300. *
  301. * @param PwInstallApplication $install
  302. * @return true PwError
  303. */
  304. public function registeInjectServices($install) {
  305. $inject = $install->getManifest()->getInjectServices();
  306. if (!$inject) return true;
  307. $alias = $hookName = array();
  308. foreach ($inject as $key => &$value) {
  309. $value['app_id'] = $install->getManifest()->getApplication('alias');
  310. $value['app_name'] = $install->getManifest()->getApplication('name');
  311. $alias[] = $value['alias'];
  312. $hookName[] = $value['hook_name'];
  313. }
  314. $this->_loadPwHookInject()->batchAdd($inject);
  315. $injects = $this->_loadPwHookInject()->batchFetchByAlias($alias);
  316. foreach ($injects as $value) {
  317. if (!in_array($value['hook_name'], $hookName)) continue;
  318. $install->addInstallLog('inject', $value['id']);
  319. }
  320. file_put_contents(DATA_PATH . 'tmp/log', 'inject!', FILE_APPEND);
  321. return true;
  322. }
  323. /**
  324. * 注册应用信息
  325. *
  326. * @param PwInstallApplication $install
  327. * @return PwError true
  328. */
  329. public function registeApplication($install) {
  330. $manifest = $install->getManifest();
  331. $application = new PwApplicationDm();
  332. $application->setAppId($install->getAppId());
  333. $application->setName($manifest->getApplication('name'));
  334. $application->setAlias($manifest->getApplication('alias'));
  335. $application->setVersion($manifest->getApplication('version'));
  336. $application->setPwVersion($manifest->getApplication('pw-version'));
  337. $application->setDescription($manifest->getApplication('description'));
  338. $application->setLogo($manifest->getApplication('logo'));
  339. $application->setWebsite($manifest->getApplication('website'));
  340. $application->setAuthorName($manifest->getApplication('author-name'));
  341. $application->setAuthorEmail($manifest->getApplication('author-email'));
  342. $application->setAuthorIcon($manifest->getApplication('author-icon'));
  343. $application->setCreatedTime(Pw::getTime());
  344. $application->setModifiedTime(Pw::getTime());
  345. // 1 - 前台入口 2 - 后台入口 4 - 非纯在线 8 - 站内应用
  346. $status = 0;
  347. if ($tmp = $install->getTmpPackage()) {
  348. if (is_file($tmp . '/' . self::CONTROLLER)) {
  349. $status |= 1;
  350. }
  351. if (is_file($tmp . '/' . self::ADMIN)) {
  352. $status |= 2;
  353. }
  354. $status |= 4;
  355. }
  356. if ($install->getManifest()->getApplication('station', '0')) {
  357. $status |= 8;
  358. }
  359. $application->setStatus($status);
  360. if (!$application->beforeAdd()) return new PwError('APPCENTER:install.mainfest.fail');
  361. $this->_load()->add($application);
  362. $install->setInstallLog('appId', $install->getAppId());
  363. file_put_contents(DATA_PATH . 'tmp/log', 'app!', FILE_APPEND);
  364. return true;
  365. }
  366. /**
  367. * 注册静态资源
  368. *
  369. * @param PwInstallApplication $install
  370. * @return PwError true
  371. */
  372. public function registeResource($install) {
  373. $manifest = $install->getManifest()->getManifest();
  374. if (!isset($manifest['res']) || !$manifest['res']) return true;
  375. $name = $install->getManifest()->getApplication('alias');
  376. $source = $install->getTmpPackage() . '/' . str_replace('.', '/', $manifest['res']);
  377. $targetPath = Wind::getRealDir('THEMES:extres', true);
  378. if (!is_dir($source)) return true;
  379. $writable = PwSystemHelper::checkWriteAble($targetPath . '/');
  380. if (!$writable) return new PwError('APPCENTER:install.mv.fail',
  381. array('{{error}}' => 'THEMES:extres.' . $name));
  382. PwApplicationHelper::copyRecursive($source, $targetPath . '/' . $name);
  383. $install->addInstallLog('packs', $targetPath . '/' . $name);
  384. file_put_contents(DATA_PATH . 'tmp/log', 'res!', FILE_APPEND);
  385. }
  386. /**
  387. *
  388. * @return PwHookInject
  389. */
  390. private function _loadPwHookInject() {
  391. return Wekit::load('SRV:hook.PwHookInject');
  392. }
  393. /**
  394. *
  395. * @return PwHooks
  396. */
  397. private function _loadPwHooks() {
  398. return Wekit::load('SRV:hook.PwHooks');
  399. }
  400. /**
  401. *
  402. * @return PwApplication
  403. */
  404. private function _load() {
  405. return Wekit::load('APPCENTER:service.PwApplication');
  406. }
  407. }
  408. ?>