api.onepunch.php 16 KB

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