manage.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. <?php
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup UnaManageCmd UNA Manage command line script
  7. * @{
  8. */
  9. $GLOBALS['bx_profiler_disable'] = true;
  10. define('BX_DOL_CRON_EXECUTE', '1');
  11. define('BX_DOL_UPGRADING', '1');
  12. /**
  13. * UNA command line interface
  14. */
  15. class BxDolManageCmd
  16. {
  17. protected $_sVer = '1.0';
  18. protected $_sCmd;
  19. protected $_sCmdOptions;
  20. protected $_sPathToUna;
  21. protected $_aSiteConfig;
  22. protected $_isQuiet = false;
  23. protected $_isSkipFilesOperation = false;
  24. protected $_aReturnCodes = array(
  25. 'success' => array ('code' => 0, 'msg' => 'Success.'),
  26. 'una not found' => array ('code' => 1, 'msg' => 'UNA wasn\'t found in the specified path: '),
  27. 'unknown cmd' => array ('code' => 2, 'msg' => 'Unknown command.'),
  28. 'db connect failed' => array ('code' => 3, 'msg' => 'Database connection failed: '),
  29. 'system update failed' => array ('code' => 4, 'msg' => 'System update failed: '),
  30. 'module operation failed' => array ('code' => 5, 'msg' => 'Module operation failed: '),
  31. 'error' => array ('code' => 9, 'msg' => 'Error occured.'),
  32. );
  33. public function __construct()
  34. {
  35. $this->_aSiteConfig = array (
  36. 'db_host' => '',
  37. 'db_port' => '',
  38. 'db_sock' => '',
  39. 'db_name' => '',
  40. 'db_user' => '',
  41. 'db_password' => '',
  42. );
  43. }
  44. public function main()
  45. {
  46. // set neccessary options
  47. $a = getopt('hvqic:u:p:o:', $this->getOptions());
  48. if (isset($a['h']))
  49. $this->finish($this->_aReturnCodes['success']['code'], $this->getHelp());
  50. if (isset($a['v']))
  51. $this->finish($this->_aReturnCodes['success']['code'], $this->getVer());
  52. if (isset($a['q']))
  53. $this->_isQuiet = true;
  54. if (isset($a['i']))
  55. $this->_isSkipFilesOperation = true;
  56. if (isset($a['u']))
  57. $this->_sPathToUna = $a['u'];
  58. if (isset($a['c']))
  59. $this->_sCmd = $a['c'];
  60. if (isset($a['o']))
  61. $this->_sCmdOptions = $a['o'];
  62. $this->_aSiteConfig = array_merge($this->_aSiteConfig, $a);
  63. // initialize environment
  64. $this->init();
  65. // run command
  66. $sMethod = $this->_sCmd ? 'cmd' . bx_gen_method_name($this->_sCmd) : 'cmdDefault';
  67. if (!method_exists($this, $sMethod))
  68. $this->finish($this->_aReturnCodes['unknown cmd']['code'], $this->_aReturnCodes['unknown cmd']['msg']);
  69. $this->$sMethod();
  70. $this->finish($this->_aReturnCodes['success']['code'], $this->_aReturnCodes['success']['msg']);
  71. }
  72. protected function getOptions()
  73. {
  74. $a = array ();
  75. foreach ($this->_aSiteConfig as $sKey => $sValue)
  76. if ('site_config' != $sKey)
  77. $a[] = "$sKey::";
  78. return $a;
  79. }
  80. protected function getVer()
  81. {
  82. return "UNA Manage Script v." . $this->_sVer;
  83. }
  84. protected function getHelp()
  85. {
  86. $s = "Usage: php manage.php [params]\n";
  87. $s .= str_pad("\t -h", 35) . "Print this help\n";
  88. $s .= str_pad("\t -q", 35) . "Quiet\n";
  89. $s .= str_pad("\t -u", 35) . "Path to UNA\n";
  90. $s .= str_pad("\t -i", 35) . "Skip files oprations, such copying and deleting when performing update commands\n";
  91. $s .= str_pad("\t -c", 35) . "Command to run:\n";
  92. $s .= str_pad("\t", 39) . "- update - options:\n";
  93. $s .= str_pad("\t", 43) . "'ignore_version_check' to ignore version comparison in DB and files\n";
  94. $s .= str_pad("\t", 39) . "- check_update - no options\n";
  95. $s .= str_pad("\t", 39) . "- update_modules - options:\n";
  96. $s .= str_pad("\t", 43) . "comma separated list of modules (ex: 'bx_nexus,bx_albums')\n";
  97. $s .= str_pad("\t", 39) . "- check_modules_updates - no options\n";
  98. $s .= str_pad("\t", 39) . "- install_modules - options:\n";
  99. $s .= str_pad("\t", 43) . "comma separated list of modules paths (ex: 'boonex/ads,boonex/wiki')\n";
  100. $s .= str_pad("\t", 39) . "- uninstall_modules - options:\n";
  101. $s .= str_pad("\t", 43) . "comma separated list of modules paths (ex: 'boonex/ads,boonex/wiki')\n";
  102. $s .= str_pad("\t", 39) . "- disable_modules - options:\n";
  103. $s .= str_pad("\t", 43) . "comma separated list of modules paths (ex: 'boonex/ads,boonex/wiki')\n";
  104. $s .= str_pad("\t", 39) . "- enable_modules - options:\n";
  105. $s .= str_pad("\t", 43) . "comma separated list of modules paths (ex: 'boonex/ads,boonex/wiki')\n";
  106. $s .= str_pad("\t -o", 35) . "Command options\n";
  107. foreach ($this->_aSiteConfig as $sKey => $sVal)
  108. if ('site_config' != $sKey)
  109. $s .= str_pad("\t --{$sKey}=<value>", 35) . "Database connection params\n";
  110. $s .= "\nIf DB params aren't specified then UNA DB params from header.inc.php are used.\n\n";
  111. $s .= "Examples:\n";
  112. $s .= "\tCheck if update is available:\n";
  113. $s .= "\tphp ./manage.php -u ../../unafolder -c check_update\n\n";
  114. $s .= "\tCheck if update is available using custom DB connection params:\n";
  115. $s .= "\tphp ./manage.php -u ../../unafolder --db_name=unadb --db_user=root --db_host=mysql --db_password=root -c check_update\n\n";
  116. $s .= "\tUpdate system files by ignoring version check and skip files copying, it's necessary when the source code is maintained using VCS:\n";
  117. $s .= "\tphp ./manage.php -u ../../unafolder --db_name=unadb --db_user=root --db_host=mysql --db_password=root -c update -i -o ignore_version_check\n\n";
  118. $s .= "\tCheck if updates for modules are available:\n";
  119. $s .= "\tphp ./manage.php -u ../../unafolder --db_name=unadb --db_user=root --db_host=mysql --db_password=root -c check_modules_updates\n\n";
  120. $s .= "\tUpdate Nexus and Albums modules by ignoring files copying operation, update must be already exists in module's 'updates' folder, to update paid modules authorize the request first in Studio > Apps > Purchases:\n";
  121. $s .= "\tphp ./manage.php -u ../../unafolder --db_name=unadb --db_user=root --db_host=mysql --db_password=root -c update_modules -i -o bx_nexus,bx_albums\n\n";
  122. $s .= "\tInstall Ads and Albums modules:\n";
  123. $s .= "\tphp ./manage.php -u ../../unafolder --db_name=unadb --db_user=root --db_host=mysql --db_password=root -c install_modules -o boonex/ads,boonex/albums\n\n";
  124. $s .= "Return codes:\n";
  125. foreach ($this->_aReturnCodes as $r) {
  126. $s .= str_pad("\t {$r['code']}", 5) . $r['msg'] . (mb_substr(trim($r['msg']), -1) == ':' ? 'message' : '') . "\n";
  127. }
  128. return $s;
  129. }
  130. protected function finish($iCode, $sMsg)
  131. {
  132. if (!$this->_isQuiet)
  133. fwrite($iCode ? STDERR : STDOUT, $sMsg . "\n");
  134. exit($iCode);
  135. }
  136. protected function init()
  137. {
  138. $this->_sPathToUna = trim($this->_sPathToUna);
  139. if ('.' == $this->_sPathToUna)
  140. $this->_sPathToUna = '';
  141. if (!$this->_sPathToUna || '/' !== $this->_sPathToUna[0]) {
  142. $aPathInfo = pathinfo(__FILE__);
  143. $this->_sPathToUna = $aPathInfo['dirname'] . '/' . $this->_sPathToUna;
  144. }
  145. $this->_sPathToUna = rtrim($this->_sPathToUna, '/');
  146. // include header.inc.php
  147. $sHeaderPath = $this->_sPathToUna . '/inc/header.inc.php';
  148. if (!file_exists($sHeaderPath))
  149. $this->finish($this->_aReturnCodes['una not found']['code'], $this->_aReturnCodes['una not found']['msg'] . $sHeaderPath);
  150. require_once($sHeaderPath);
  151. // db connection
  152. if (!empty($this->_aSiteConfig['db_name'])) {
  153. BxDolDb::getInstance()->cacheParamsClear();
  154. BxDolDb::getInstance()->disconnect();
  155. unset($GLOBALS['bxDolClasses']['BxDolDb']);
  156. $sErr = null;
  157. try {
  158. $oDb = BxDolDb::getInstanceWithConf(array(
  159. 'host' => $this->_aSiteConfig['db_host'],
  160. 'port' => $this->_aSiteConfig['db_port'],
  161. 'sock' => $this->_aSiteConfig['db_sock'],
  162. 'name' => $this->_aSiteConfig['db_name'],
  163. 'user' => $this->_aSiteConfig['db_user'],
  164. 'pwd' => $this->_aSiteConfig['db_password'],
  165. ), $sErr);
  166. $GLOBALS['bxDolClasses']['BxDolUpgradeDb'] = $oDb;
  167. } catch (Exception $e) {
  168. $this->finish($this->_aReturnCodes['db connect failed']['code'], $this->_aReturnCodes['db connect failed']['msg'] . $e->getMessage());
  169. }
  170. }
  171. }
  172. function cmdCheckUpdate()
  173. {
  174. $oUpgrader = bx_instance('BxDolUpgrader');
  175. $aUpdateInfo = $oUpgrader->getVersionUpdateInfo();
  176. if (!isset($aUpdateInfo['patch']))
  177. $this->finish($this->_aReturnCodes['success']['code'], 'No system update available');
  178. $s = str_pad(bx_get_ver(), 12) . str_pad($aUpdateInfo['patch']['ver'], 12) . $aUpdateInfo['latest_version'];
  179. $this->finish($this->_aReturnCodes['success']['code'], $s);
  180. }
  181. function cmdUpdate()
  182. {
  183. $aOptions = $this->_parseOptions($this->_sCmdOptions);
  184. $oCronDb = BxDolCronQuery::getInstance();
  185. $aCronJobs = $oCronDb->getTransientJobs();
  186. if (!isset($aCronJobs['sys_perform_upgrade'])) {
  187. $oUpgrader = bx_instance('BxDolUpgrader');
  188. $aUpdateInfo = $oUpgrader->getVersionUpdateInfo();
  189. $bUpgrade = $oUpgrader->isUpgradeAvailable($aUpdateInfo);
  190. if (!$bUpgrade)
  191. $this->finish($this->_aReturnCodes['system update failed']['code'], $this->_aReturnCodes['system update failed']['msg'] . 'you have up to date version');
  192. if(!$oUpgrader->prepare(false, in_array('ignore_version_check', $aOptions)))
  193. $this->finish($this->_aReturnCodes['system update failed']['code'], $this->_aReturnCodes['system update failed']['msg'] . $oUpgrader->getError());
  194. }
  195. $aCronJobs = $oCronDb->getTransientJobs();
  196. if (empty($aCronJobs['sys_perform_upgrade']))
  197. $this->finish($this->_aReturnCodes['system update failed']['code'], $this->_aReturnCodes['system update failed']['msg'] . 'no cron job with patch path was found');
  198. $sPatchDir = BX_DIRECTORY_PATH_ROOT . $aCronJobs['sys_perform_upgrade']['file'];
  199. $sPatchDir = str_replace('BxDolUpgradeCron.php', '', $sPatchDir);
  200. define ('BX_UPGRADE_DIR_UPGRADES', $sPatchDir . 'files/');
  201. require_once($sPatchDir . 'classes/BxDolUpgradeController.php');
  202. require_once($sPatchDir . 'classes/BxDolUpgradeUtil.php');
  203. require_once($sPatchDir . 'classes/BxDolUpgradeDb.php');
  204. $oController = new BxDolUpgradeController();
  205. if ($oController->setMaintenanceMode(true)) {
  206. $sFolder = $oController->getAvailableUpgrade();
  207. if ($sFolder && $oController->runUpgrade($sFolder, in_array('ignore_version_check', $aOptions), $this->_isSkipFilesOperation)) {
  208. setParam('sys_revision', getParam('sys_revision') + 1);
  209. $oController->writeLog();
  210. @bx_rrmdir($sUpgradeDir);
  211. }
  212. $oController->setMaintenanceMode(false);
  213. }
  214. $oCronDb->deleteTransientJobs();
  215. if ($sErrorMsg = $oController->getErrorMsg()) {
  216. $this->finish($this->_aReturnCodes['system update failed']['code'], $this->_aReturnCodes['system update failed']['msg'] . $sErrorMsg);
  217. }
  218. }
  219. function cmdCheckModulesUpdates()
  220. {
  221. $aDownloaded = BxDolStudioInstallerUtils::getInstance()->getUpdates();
  222. $a = BxDolStudioInstallerUtils::getInstance()->checkUpdates();
  223. if (!$a)
  224. $this->finish($this->_aReturnCodes['success']['code'], 'No modules updates available');
  225. $s = '';
  226. foreach ($a as $r) {
  227. $s .= str_pad($r['name'], 20) . str_pad($r['file_version'], 12) . str_pad($r['file_version_to'], 12);
  228. $sDir = '';
  229. foreach ($aDownloaded as $j) {
  230. if ($j['module_name'] == $r['name'])
  231. $sDir .= $j['dir'];
  232. }
  233. if (!$sDir)
  234. $sDir = "Downloaded update wasn't found";
  235. $s .= "$sDir\n";
  236. }
  237. $this->finish($this->_aReturnCodes['success']['code'], trim($s));
  238. }
  239. function cmdUpdateModules()
  240. {
  241. // TODO: option to disable files operations
  242. $aModules = $this->_parseOptions($this->_sCmdOptions);
  243. if (!$aModules)
  244. $this->finish($this->_aReturnCodes['module operation failed']['code'], 'No modules were provided');
  245. $bErr = false;
  246. $s = "";
  247. $a = BxDolStudioInstallerUtils::getInstance()->getUpdates();
  248. if (!$a)
  249. $this->finish($this->_aReturnCodes['success']['code'], 'No modules updates available');
  250. foreach ($a as $r) {
  251. if (!in_array($r['module_name'], $aModules) && !in_array($r['module_dir'], $aModules))
  252. continue;
  253. $aParams = ['module_name' => $r['module_name']];
  254. if ($this->_isSkipFilesOperation)
  255. $aParams['disabled_actions'] = ['update_files'];
  256. $aRes = BxDolStudioInstallerUtils::getInstance()->perform($r['dir'], 'update', $aParams);
  257. $s .= str_pad($r['module_name'], 20);
  258. if (!isset($aRes['code']) || $aRes['code'] !== BX_DOL_STUDIO_IU_RC_SUCCESS) {
  259. $bErr = true;
  260. $s .= "ERROR " . html_entity_decode($aRes['message']) . "\n";
  261. } else {
  262. $s .= "OK\n";
  263. }
  264. }
  265. if (!$s)
  266. $this->finish($this->_aReturnCodes['module operation failed']['code'], 'No downloaded updates or no updates were found for specified modules');
  267. $iCode = $bErr ? $this->_aReturnCodes['module operation failed']['code'] : $this->_aReturnCodes['success']['code'];
  268. $this->finish($iCode, trim($s));
  269. /*
  270. BxDolStudioInstallerUtils::getInstance()->performModulesUpgrade(array(
  271. 'directly' => true,
  272. 'transient' => false,
  273. 'autoupdate' => true
  274. ));
  275. */
  276. }
  277. function cmdInstallModules()
  278. {
  279. $this->_cmdModules('install', ['auto_enable' => true, 'html_response' => false]);
  280. }
  281. function cmdUninstallModules()
  282. {
  283. $this->_cmdModules('uninstall', ['html_response' => false]);
  284. }
  285. function cmdEnableModules()
  286. {
  287. $this->_cmdModules('enable', ['html_response' => false]);
  288. }
  289. function cmdDisableModules()
  290. {
  291. $this->_cmdModules('disable', ['html_response' => false]);
  292. }
  293. function _parseOptions($s)
  294. {
  295. if (!$s)
  296. return [];
  297. $a = explode(',', trim($s));
  298. foreach ($a as $k => $v)
  299. $a[$k] = trim($v);
  300. return $a;
  301. }
  302. function _cmdModules($sOperation, $aOptions = [])
  303. {
  304. $aModules = $this->_parseOptions($this->_sCmdOptions);
  305. foreach ($aModules as $sModule) {
  306. $sModule = trim($sModule, '/') . '/';
  307. $a = BxDolStudioInstallerUtils::getInstance()->perform($sModule, $sOperation, array('auto_enable' => true, 'html_response' => false));
  308. if (!isset($a['code']) || $a['code'] !== BX_DOL_STUDIO_IU_RC_SUCCESS)
  309. $this->finish($this->_aReturnCodes['module operation failed']['code'], $this->_aReturnCodes['module operation failed']['msg'] . (!empty($a['message']) ? $a['message'] : 'Error occured.') . ' (' . $sOperation . ': ' . $sModule . ')');
  310. }
  311. }
  312. }
  313. $o = new BxDolManageCmd();
  314. $o->main();
  315. /** @} */