api.onepunch.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. <?php
  2. /**
  3. * Allows you to be an Saitama!
  4. */
  5. class OnePunch {
  6. /**
  7. * Contains available punch scripts as alias=>data
  8. *
  9. * @var array
  10. */
  11. protected $punchScripts = array();
  12. /**
  13. * System message helper object placeholder
  14. *
  15. * @var object
  16. */
  17. protected $messages = '';
  18. /**
  19. * Placeholder for ONEPUNCH_DEFAULT_SORT_FIELD
  20. *
  21. * @var string
  22. */
  23. protected $defaultSortField = '';
  24. /**
  25. * System config object placeholder
  26. *
  27. * @var object
  28. */
  29. protected $ubConfig = '';
  30. /**
  31. * Punch scripts database abstraction layer placeholder
  32. *
  33. * @var object
  34. */
  35. protected $punchDb = '';
  36. /**
  37. * Some predefined URLs, routes, tables etc...
  38. */
  39. const URL_DEVCON = '?module=sqlconsole&devconsole=true';
  40. const TABLE_DATASOURCE = 'punchscripts';
  41. // ⠀⠀⠀⣠⣶⡾⠏⠉⠙⠳⢦⡀⠀⠀⠀⢠⠞⠉⠙⠲⡀⠀
  42. // ⠀⠀⠀⣴⠿⠏⠀⠀⠀⠀⠀⠀⢳⡀⠀⡏⠀⠀⠀⠀⠀⢷
  43. // ⠀⠀⢠⣟⣋⡀⢀⣀⣀⡀⠀⣀⡀⣧⠀⢸⠀⠀⠀⠀⠀ ⡇
  44. // ⠀⠀⢸⣯⡭⠁⠸⣛⣟⠆⡴⣻⡲⣿⠀⣸⠀⠀OK⠀ ⡇
  45. // ⠀⠀⣟⣿⡭⠀⠀⠀⠀⠀⢱⠀⠀⣿⠀⢹⠀⠀⠀⠀⠀ ⡇
  46. // ⠀⠀⠙⢿⣯⠄⠀⠀⠀⢀⡀⠀⠀⡿⠀⠀⡇⠀⠀⠀⠀⡼
  47. // ⠀⠀⠀⠀⠹⣶⠆⠀⠀⠀⠀⠀⡴⠃⠀⠀⠘⠤⣄⣠⠞⠀
  48. // ⠀⠀⠀⠀⠀⢸⣷⡦⢤⡤⢤⣞⣁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
  49. // ⠀⠀⢀⣤⣴⣿⣏⠁⠀⠀⠸⣏⢯⣷⣖⣦⡀⠀⠀⠀⠀⠀⠀
  50. // ⢀⣾⣽⣿⣿⣿⣿⠛⢲⣶⣾⢉⡷⣿⣿⠵⣿⠀⠀⠀⠀⠀⠀
  51. // ⣼⣿⠍⠉⣿⡭⠉⠙⢺⣇⣼⡏⠀⠀⠀⣄⢸⠀⠀⠀⠀⠀⠀
  52. // ⣿⣿⣧⣀⣿………⣀⣰⣏⣘⣆⣀⠀⠀
  53. /**
  54. * Creates new object instance
  55. *
  56. * @param string alias only one alias to load
  57. *
  58. * @return void
  59. */
  60. public function __construct($alias = '') {
  61. $this->loadOptions();
  62. $this->initMessages();
  63. $this->initDatabase();
  64. $this->loadScripts($alias);
  65. }
  66. /**
  67. * Inits system message helper object instance for further usage
  68. *
  69. * @return void
  70. */
  71. protected function initMessages() {
  72. $this->messages = new UbillingMessageHelper();
  73. }
  74. /**
  75. * Inits database abstraction layer
  76. *
  77. * @return void
  78. */
  79. protected function initDatabase() {
  80. $this->punchDb = new NyanORM(self::TABLE_DATASOURCE);
  81. }
  82. /**
  83. * Load required configs and sets some properties depends by options
  84. *
  85. * @return void
  86. */
  87. protected function loadOptions() {
  88. global $ubillingConfig;
  89. $this->ubConfig = $ubillingConfig;
  90. $customSortField = $this->ubConfig->getAlterParam('ONEPUNCH_DEFAULT_SORT_FIELD');
  91. if ($customSortField) {
  92. $this->defaultSortField = $customSortField;
  93. }
  94. }
  95. /**
  96. * Loads existing punch scripts from database
  97. *
  98. * @param string $alias
  99. *
  100. * @return void
  101. */
  102. protected function loadScripts($alias = '') {
  103. $alias = ubRouting::filters($alias, 'callback', 'vf');
  104. if (!empty($alias)) {
  105. $this->punchDb->where('alias', '=', $alias);
  106. }
  107. if (!empty($this->defaultSortField)) {
  108. $this->punchDb->orderBy($this->defaultSortField, 'ASC');
  109. }
  110. $this->punchScripts = $this->punchDb->getAll('alias');
  111. }
  112. /**
  113. * Returns array of loaded scripts as alias=>scriptData
  114. *
  115. * @return array
  116. */
  117. public function getAllScripts() {
  118. return($this->punchScripts);
  119. }
  120. /**
  121. * Checks is some script alias unused?
  122. *
  123. * @param sring $alias
  124. *
  125. * @return bool false - script exists, true - alias free.
  126. */
  127. protected function checkAlias($alias) {
  128. $alias = ubRouting::filters($alias, 'callback', 'vf');
  129. $result = true;
  130. if (isset($this->punchScripts[$alias])) {
  131. $result = false;
  132. }
  133. return ($result);
  134. }
  135. /**
  136. * Renders new script creation form
  137. *
  138. * @return string
  139. */
  140. public function renderCreateForm() {
  141. $result = '';
  142. $inputs = '';
  143. $namePreset = (ubRouting::checkPost('newscriptname')) ? ubRouting::post('newscriptname') : '';
  144. $aliasPreset = (ubRouting::checkPost('newscriptalias')) ? ubRouting::post('newscriptalias') : '';
  145. $contentPreset = (ubRouting::checkPost('newscriptcontent')) ? ubRouting::post('newscriptcontent') : '';
  146. // sanjou! hisshou! shijou saikyou
  147. // nan dattenda? FURASUTOREESHON ore wa tomaranai
  148. $inputs .= wf_TextInput('newscriptname', __('Name'), $namePreset, true, 30);
  149. $inputs .= wf_TextInput('newscriptalias', __('Alias'), $aliasPreset, true, 15, 'alphanumeric');
  150. $inputs .= wf_tag('textarea', false, 'fileeditorarea', 'name="newscriptcontent" cols="145" rows="30" spellcheck="false"');
  151. $inputs .= $contentPreset;
  152. $inputs .= wf_tag('textarea', true);
  153. $inputs .= wf_Submit(__('Create'));
  154. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  155. $result .= wf_delimiter();
  156. $result .= wf_BackLink(self::URL_DEVCON);
  157. return ($result);
  158. }
  159. /**
  160. * Renders script editing form
  161. *
  162. * @param string $alias
  163. *
  164. * @return string
  165. */
  166. public function renderEditForm($alias) {
  167. $result = '';
  168. $alias = ubRouting::filters($alias, 'callback', 'vf');
  169. if (isset($this->punchScripts[$alias])) {
  170. $inputs = '';
  171. $scriptData = $this->punchScripts[$alias];
  172. $namePreset = $scriptData['name'];
  173. $aliasPreset = $scriptData['alias'];
  174. $contentPreset = htmlentities($scriptData['content'], ENT_COMPAT, "UTF-8");
  175. $scriptId = $scriptData['id'];
  176. $inputs .= wf_HiddenInput('editscriptid', $scriptId);
  177. $inputs .= wf_HiddenInput('editscriptoldalias', $aliasPreset);
  178. $inputs .= wf_TextInput('editscriptname', __('Name'), $namePreset, true, 30);
  179. $inputs .= wf_TextInput('editscriptalias', __('Alias'), $aliasPreset, true, 15, 'alphanumeric');
  180. $inputs .= wf_tag('textarea', false, 'fileeditorarea', 'name="editscriptcontent" cols="145" rows="30" spellcheck="false"');
  181. $inputs .= $contentPreset;
  182. $inputs .= wf_tag('textarea', true);
  183. $inputs .= wf_Submit(__('Save'));
  184. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  185. $result .= wf_delimiter();
  186. $result .= wf_BackLink(self::URL_DEVCON);
  187. }
  188. return ($result);
  189. }
  190. /**
  191. * Creates new script in database
  192. *
  193. * @param string $alias
  194. * @param string $name
  195. * @param string $content
  196. *
  197. * @return void/string on error
  198. */
  199. public function createScript($alias, $name, $content) {
  200. $result = '';
  201. $alias = ubRouting::filters($alias, 'callback', 'vf');
  202. $name = ubRouting::filters($name, 'mres');
  203. $content = ubRouting::filters($content, 'mres');
  204. if ($this->checkAlias($alias)) {
  205. $this->punchDb->data('alias', $alias);
  206. $this->punchDb->data('name', $name);
  207. $this->punchDb->data('content', $content);
  208. $this->punchDb->create();
  209. log_register('ONEPUNCH CREATE ALIAS `' . $alias . '`');
  210. } else {
  211. $result .= __('Something went wrong') . ': ' . __('Script with this alias already exists');
  212. log_register('ONEPUNCH CREATE ALIAS `' . $alias . '` FAIL');
  213. }
  214. return ($result);
  215. }
  216. /**
  217. * Deletes some script from database by his alias
  218. *
  219. * @param string $alias
  220. *
  221. * @return void/string on error
  222. */
  223. public function deleteScript($alias) {
  224. $result = '';
  225. $alias = ubRouting::filters($alias, 'callback', 'vf');
  226. if (isset($this->punchScripts[$alias])) {
  227. $this->punchDb->where('alias', '=', $alias);
  228. $this->punchDb->delete();
  229. log_register('ONEPUNCH DELETE ALIAS `' . $alias . '`');
  230. } else {
  231. $result .= __('Something went wrong') . ': ' . __('Script with this alias not exists');
  232. log_register('ONEPUNCH DELETE ALIAS `' . $alias . '` FAIL');
  233. }
  234. return ($result);
  235. }
  236. /**
  237. * Saves script data into database
  238. *
  239. * @return void
  240. */
  241. public function saveScript() {
  242. if (ubRouting::checkPost(array('editscriptid', 'editscriptoldalias', 'editscriptname', 'editscriptalias', 'editscriptcontent'))) {
  243. $scriptId = ubRouting::post('editscriptid', 'int');
  244. $newScriptAlias = ubRouting::post('editscriptalias', 'callback', 'vf');
  245. $oldScriptAlias = ubRouting::post('editscriptoldalias', 'callback', 'vf');
  246. $newScriptName = ubRouting::post('editscriptname', 'mres');
  247. $newScriptContent = ubRouting::post('editscriptcontent', 'mres');
  248. if (isset($this->punchScripts[$oldScriptAlias])) {
  249. $scriptData = $this->punchScripts[$oldScriptAlias];
  250. if ($scriptData['alias'] != $newScriptAlias) {
  251. if ($this->checkAlias($newScriptAlias)) {
  252. $this->punchDb->where('id', '=', $scriptId);
  253. $this->punchDb->data('alias', $newScriptAlias);
  254. $this->punchDb->save();
  255. log_register('ONEPUNCH CHANGE ALIAS `' . $oldScriptAlias . '` ON `' . $newScriptAlias . '`');
  256. } else {
  257. log_register('ONEPUNCH CHANGE ALIAS `' . $newScriptAlias . '` FAIL');
  258. }
  259. }
  260. if ($scriptData['name'] != $newScriptName) {
  261. $this->punchDb->where('id', '=', $scriptId);
  262. $this->punchDb->data('name', $newScriptName);
  263. $this->punchDb->save();
  264. log_register('ONEPUNCH CHANGE NAME `' . $oldScriptAlias . '`');
  265. }
  266. if ($scriptData['content'] != $newScriptContent) {
  267. $this->punchDb->where('id', '=', $scriptId);
  268. $this->punchDb->data('content', $newScriptContent);
  269. $this->punchDb->save();
  270. log_register('ONEPUNCH CHANGE CONTENT `' . $oldScriptAlias . '`');
  271. }
  272. }
  273. }
  274. }
  275. /**
  276. * Performs old dev console code templates migration into one-punch scripts
  277. *
  278. * @return void
  279. */
  280. public function importOldTemplates() {
  281. $keyMask = 'PHPCONSOLETEMPLATE:';
  282. $allTemplateKeys = zb_StorageFindKeys($keyMask);
  283. if (!empty($allTemplateKeys)) {
  284. foreach ($allTemplateKeys as $eachTemplateKey) {
  285. $newAlias = str_replace($keyMask, '', $eachTemplateKey['key']);
  286. $templateRaw = zb_StorageGet($eachTemplateKey['key']);
  287. @$templateData = unserialize($templateRaw);
  288. if (!empty($templateData)) {
  289. if ((isset($templateData['name'])) AND ( isset($templateData['body']))) {
  290. if ($this->checkAlias($newAlias)) {
  291. //alias not exists yet
  292. $this->createScript($newAlias, $templateData['name'], $templateData['body']);
  293. //flush old code template
  294. zb_StorageDelete($eachTemplateKey['key']);
  295. }
  296. }
  297. }
  298. }
  299. }
  300. }
  301. /**
  302. * Renders list of available punch scripts with some controls
  303. *
  304. * @return string
  305. */
  306. public function renderScriptsList() {
  307. $result = '';
  308. if (!empty($this->punchScripts)) {
  309. $cells = wf_TableCell(__('Name'));
  310. $cells .= wf_TableCell(__('Alias'));
  311. $cells .= wf_TableCell(__('Actions'));
  312. $rows = wf_TableRow($cells, 'row1');
  313. foreach ($this->punchScripts as $io => $each) {
  314. $runLink = wf_JSAlert(self::URL_DEVCON . '&runscript=' . $each['alias'], $each['name'], 'Insert this template into PHP console');
  315. $cells = wf_TableCell($runLink);
  316. $cells .= wf_TableCell($each['alias']);
  317. $actLinks = wf_JSAlert(self::URL_DEVCON . '&delscript=' . $each['alias'], web_delete_icon(), $this->messages->getDeleteAlert()) . ' ';
  318. $actLinks .= wf_JSAlert(self::URL_DEVCON . '&editscript=' . $each['alias'], web_edit_icon(), $this->messages->getEditAlert());
  319. $cells .= wf_TableCell($actLinks);
  320. $rows .= wf_TableRow($cells, 'row5');
  321. }
  322. $result .= wf_TableBody($rows, '100%', 0, 'sortable');
  323. } else {
  324. $result .= $this->messages->getStyledMessage(__('No available code templates'), 'warning');
  325. $result .= wf_tag('br');
  326. $result .= wf_JSAlertStyled(self::URL_DEVCON . '&importoldcodetemplates=true', wf_img('skins/shovel.png') . ' ' . __('Import old code templates if available'), $this->messages->getEditAlert(), 'ubButton');
  327. $result .= wf_tag('br');
  328. }
  329. return ($result);
  330. }
  331. /**
  332. * Returns executable content of existing punch script
  333. *
  334. * @param string $alias
  335. *
  336. * @return string
  337. */
  338. public function getScriptContent($alias) {
  339. $alias = ubRouting::filters($alias, 'callback', 'vf');
  340. $result = '';
  341. if (isset($this->punchScripts[$alias])) {
  342. $result .= $this->punchScripts[$alias]['content'];
  343. }
  344. return ($result);
  345. }
  346. /**
  347. * Checks is some script alias exists?
  348. *
  349. * @param string $alias
  350. *
  351. * @return bool
  352. */
  353. public function isAliasFree($alias) {
  354. return($this->checkAlias($alias));
  355. }
  356. /**
  357. * Installs some third-party script
  358. *
  359. * @param array $scriptData
  360. *
  361. * @return void/string on error
  362. */
  363. public function installScript($scriptData) {
  364. $result = '';
  365. if (is_array($scriptData)) {
  366. if (isset($scriptData['alias']) AND isset($scriptData['name']) AND isset($scriptData['content'])) {
  367. $alias = $scriptData['alias'];
  368. $name = $scriptData['name'];
  369. $content = $scriptData['content'];
  370. if (!empty($alias) AND !empty($name) AND !empty($content)) {
  371. if ($this->isAliasFree($alias)) {
  372. $result .= $this->createScript($alias, $name, $content);
  373. } else {
  374. $result .= __('One-punch') . ' ' . __('Alias') . ' ' . _('already exists');
  375. }
  376. } else {
  377. $result .= __('One-punch') . ' ' . __('script') . ' ' . _('is corrupted');
  378. }
  379. } else {
  380. $result .= __('One-punch') . ' ' . __('script') . ' ' . _('is corrupted');
  381. }
  382. } else {
  383. $result .= __('One-punch') . ' ' . __('script') . ' ' . _('is corrupted');
  384. }
  385. return($result);
  386. }
  387. }