api.ptv.php 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131
  1. <?php
  2. /**
  3. * ProstoTV Ubilling abstraction layer
  4. *
  5. * https://docs.api.prosto.tv/
  6. */
  7. class PTV {
  8. /**
  9. * Contains sytem alter.config as key=>value
  10. *
  11. * @var array
  12. */
  13. protected $altCfg = array();
  14. /**
  15. * Contains login preloaded from config
  16. *
  17. * @var string
  18. */
  19. protected $login = '';
  20. /**
  21. * Contains password preloaded from config
  22. *
  23. * @var string
  24. */
  25. protected $password = '';
  26. /**
  27. * ProstoTV low-level API abstraction layer
  28. *
  29. * @var object
  30. */
  31. protected $api = '';
  32. /**
  33. * Contains all available system users data as login=>userdata
  34. *
  35. * @var array
  36. */
  37. protected $allUserData = array();
  38. /**
  39. * Contains all subscribers data as login=>subscriberData
  40. *
  41. * @var array
  42. */
  43. protected $allSubscribers = array();
  44. /**
  45. * Contains all tariffs data as serviceid=>tariffData
  46. *
  47. * @var string
  48. */
  49. protected $allTariffs = array();
  50. /**
  51. * Subscribers database abstraction layer
  52. *
  53. * @var object
  54. */
  55. protected $subscribersDb = '';
  56. /**
  57. * Tariffs database abstraction layer
  58. *
  59. * @var object
  60. */
  61. protected $tariffsDb = '';
  62. /**
  63. * System message helper object placeholder
  64. *
  65. * @var object
  66. */
  67. protected $messages = '';
  68. /**
  69. * Predefined routes, options etc.
  70. */
  71. const OPTION_LOGIN = 'PTV_LOGIN';
  72. const OPTION_PASSWORD = 'PTV_PASSWORD';
  73. const TABLE_SUBSCRIBERS = 'ptv_subscribers';
  74. const TABLE_TARIFFS = 'ptv_tariffs';
  75. const UNDEF = 'undefined_';
  76. const NEW_WINDOW = 'TARGET="_BLANK"';
  77. const URL_ME = '?module=prostotv';
  78. const URL_USERPROFILE = '?module=userprofile&username=';
  79. const ROUTE_SUBLIST = 'subscribers';
  80. const ROUTE_SUBAJ = 'ajaxlist';
  81. const ROUTE_SUBVIEW = 'showsubscriber';
  82. const ROUTE_TARIFFS = 'tariffs';
  83. const ROUTE_BUNDLES = 'bundles';
  84. const ROUTE_PLCREATE = 'createplaylist';
  85. const ROUTE_PLDEL = 'deleteplaylist';
  86. const ROUTE_SUBID = 'subscriberid';
  87. const ROUTE_DEVCREATE = 'createdevice';
  88. const ROUTE_DEVDEL = 'deletedevice';
  89. const ROUTE_SUBLOOKUP = 'username';
  90. const ROUTE_TARDEL = 'deletetariff';
  91. const PROUTE_SUBREG = 'registersubscriber';
  92. const PROUTE_CREATETARIFFID = 'newtariffserviceid';
  93. const PROUTE_CREATETARIFFMAIN = 'newtariffmainflag';
  94. const PROUTE_CREATETARIFFNAME = 'newtariffname';
  95. const PROUTE_CREATETARIFFCHANS = 'newtariffchans';
  96. const PROUTE_CREATETARIFFFEE = 'newtarifffee';
  97. const PROUTE_TARIFFEDITSUBID = 'changetariffsubscriberid';
  98. const PROUTE_SETMAINTARIFFID = 'changemaintariffserviceid';
  99. const PROUTE_SETADDTARIFFID = 'changeaddionaltariffs';
  100. /**
  101. * I keep my eyes low, looking for my rival
  102. * Eyes Low
  103. * Playing with the rifle
  104. * White dope
  105. * Feeling homicidal
  106. * Ride slow
  107. * Fucking up your spinal
  108. */
  109. public function __construct() {
  110. $this->initMessages();
  111. $this->loadConfig();
  112. $this->setOptions();
  113. $this->initApi();
  114. $this->loadUserData();
  115. $this->initSubscribersDb();
  116. $this->initTariffsDb();
  117. $this->loadSubscribers();
  118. $this->loadTariffs();
  119. }
  120. /**
  121. * Preloads required configs into protected props
  122. *
  123. * @global object $ubillingConfig
  124. *
  125. * @return void
  126. */
  127. protected function loadConfig() {
  128. global $ubillingConfig;
  129. $this->altCfg = $ubillingConfig->getAlter();
  130. }
  131. /**
  132. * Sets required properties via config options
  133. *
  134. * @return void
  135. */
  136. protected function setOptions() {
  137. $this->login = $this->altCfg[self::OPTION_LOGIN];
  138. $this->password = $this->altCfg[self::OPTION_PASSWORD];
  139. }
  140. /**
  141. * Inits system message helper
  142. *
  143. * @return void
  144. */
  145. protected function initMessages() {
  146. $this->messages = new UbillingMessageHelper();
  147. }
  148. /**
  149. * Inits low-level API for further usage
  150. *
  151. * @return void
  152. */
  153. protected function initApi() {
  154. require_once ('api/libs/api.prostotv.php');
  155. $this->api = new UTG\ProstoTV($this->login, $this->password);
  156. }
  157. /**
  158. * Inits subscribers database abstraction layer
  159. *
  160. * @return void
  161. */
  162. protected function initSubscribersDb() {
  163. $this->subscribersDb = new NyanORM(self::TABLE_SUBSCRIBERS);
  164. }
  165. /**
  166. * Inits tariffs database abstraction layer
  167. *
  168. * @return void
  169. */
  170. protected function initTariffsDb() {
  171. $this->tariffsDb = new NyanORM(self::TABLE_TARIFFS);
  172. }
  173. /**
  174. * Loads available subscribers from database
  175. *
  176. * @return void
  177. */
  178. protected function loadSubscribers() {
  179. $this->allSubscribers = $this->subscribersDb->getAll('login');
  180. }
  181. /**
  182. * Loads available tariffs from database
  183. *
  184. * @return void
  185. */
  186. protected function loadTariffs() {
  187. $this->allTariffs = $this->tariffsDb->getAll('serviceid');
  188. }
  189. /**
  190. * Loads available system users data
  191. *
  192. * @return void
  193. */
  194. protected function loadUserData() {
  195. $this->allUserData = zb_UserGetAllData();
  196. }
  197. /**
  198. * Registers a new user
  199. *
  200. * @param string $userLogin
  201. *
  202. * @return array/bool on error
  203. */
  204. public function userRegister($userLogin) {
  205. $result = false;
  206. $userLogin = ubRouting::filters($userLogin, 'mres');
  207. //user exists
  208. if (isset($this->allUserData[$userLogin])) {
  209. //not registered yet
  210. if (!isset($this->allSubscribers[$userLogin])) {
  211. $userData = $this->allUserData[$userLogin];
  212. $newPassword = $userData['Password'];
  213. $userRealName = $userData['realname'];
  214. $userRealNameParts = explode(' ', $userRealName);
  215. if (sizeof($userRealNameParts == 3)) {
  216. $firstName = @$userRealNameParts[1];
  217. $middleName = @$userRealNameParts[2];
  218. $lastName = @$userRealNameParts[0];
  219. } else {
  220. $firstName = self::UNDEF . $userLogin;
  221. $middleName = self::UNDEF . $userLogin;
  222. $lastName = self::UNDEF . $userLogin;
  223. }
  224. $requestParams = array(
  225. 'first_name' => $firstName,
  226. 'middle_name' => $middleName,
  227. 'last_name' => $lastName,
  228. 'note' => $userLogin,
  229. 'password' => $newPassword
  230. );
  231. $result = $this->api->post('/objects', $requestParams);
  232. //log subscriber
  233. $newId = $result['id'];
  234. $this->subscribersDb->data('date', curdatetime());
  235. $this->subscribersDb->data('subscriberid', $newId);
  236. $this->subscribersDb->data('login', $userLogin);
  237. $this->subscribersDb->data('active', '1');
  238. $this->subscribersDb->create();
  239. log_register('PTV SUB REGISTER (' . $userLogin . ') AS [' . $newId . ']');
  240. } else {
  241. log_register('PTV SUB REGISTER (' . $userLogin . ') DUPLICATE FAIL');
  242. }
  243. } else {
  244. log_register('PTV SUB REGISTER (' . $userLogin . ') NOTEXIST FAIL');
  245. }
  246. return($result);
  247. }
  248. /**
  249. * Returns subscriber remote data
  250. *
  251. * @param string $userLogin
  252. *
  253. * @return array/bool
  254. */
  255. public function getUserData($userLogin) {
  256. $result = false;
  257. if (isset($this->allSubscribers[$userLogin])) {
  258. $subscriberId = $this->allSubscribers[$userLogin]['subscriberid'];
  259. $reply = $this->api->get('/objects/' . $subscriberId);
  260. if ($reply) {
  261. $result = $reply;
  262. }
  263. }
  264. return($result);
  265. }
  266. /**
  267. * Checks is some subscriberId associated with registered user?
  268. *
  269. * @param int $subscriberId
  270. *
  271. * @return bool
  272. */
  273. public function isValidSubscriber($subscriberId) {
  274. $subscriberId = ubRouting::filters($subscriberId, 'int');
  275. $result = false;
  276. if (!empty($this->allSubscribers)) {
  277. foreach ($this->allSubscribers as $io => $each) {
  278. if ($each['subscriberid'] == $subscriberId) {
  279. $result = true;
  280. }
  281. }
  282. }
  283. return($result);
  284. }
  285. /**
  286. * Returns array of all existing user playlists
  287. *
  288. * @param int $subscriberId
  289. *
  290. * @return array/bool
  291. */
  292. public function getPlaylistsAll($subscriberId) {
  293. $result = false;
  294. if ($this->isValidSubscriber($subscriberId)) {
  295. $reply = $this->api->get('objects/' . $subscriberId . '/playlists');
  296. if (isset($reply['playlists'])) {
  297. $result = $reply['playlists'];
  298. }
  299. }
  300. return($result);
  301. }
  302. /**
  303. * Returns existing subscriber user login by its ID
  304. *
  305. * @param int $subscriberId
  306. *
  307. * @return string/bool
  308. */
  309. public function getSubscriberLogin($subscriberId) {
  310. $result = false;
  311. if (!empty($this->allSubscribers)) {
  312. foreach ($this->allSubscribers as $io => $each) {
  313. if ($each['subscriberid'] == $subscriberId) {
  314. $result = $each['login'];
  315. }
  316. }
  317. }
  318. return($result);
  319. }
  320. /**
  321. * Returns subscripber ID by some of the users login
  322. *
  323. * @param string $userLogin
  324. *
  325. * @return int/bool
  326. */
  327. public function getSubscriberId($userLogin) {
  328. $result = false;
  329. if (isset($this->allSubscribers[$userLogin])) {
  330. $result = $this->allSubscribers[$userLogin]['subscriberid'];
  331. }
  332. return($result);
  333. }
  334. /**
  335. * Creates new playlist for some subscriber
  336. *
  337. * @param int $subscriberId
  338. *
  339. * @return array/bool
  340. */
  341. public function createPlayList($subscriberId) {
  342. $result = false;
  343. if ($this->isValidSubscriber($subscriberId)) {
  344. $userLogin = $this->getSubscriberLogin($subscriberId);
  345. $result = $this->api->post('objects/' . $subscriberId . '/playlists');
  346. log_register('PTV PLAYLIST CREATE SUB (' . $userLogin . ') AS [' . $subscriberId . ']');
  347. }
  348. return($result);
  349. }
  350. /**
  351. * Creates some device for subscriber
  352. *
  353. * @param int $subscriberId
  354. *
  355. * @return array/bool
  356. */
  357. public function createDevice($subscriberId) {
  358. $result = false;
  359. if ($this->isValidSubscriber($subscriberId)) {
  360. $userLogin = $this->getSubscriberLogin($subscriberId);
  361. $result = $this->api->post('objects/' . $subscriberId . '/devices');
  362. log_register('PTV DEVICE CREATE SUB (' . $userLogin . ') AS [' . $subscriberId . ']');
  363. }
  364. return($result);
  365. }
  366. /**
  367. * Deletes some device for subscriber
  368. *
  369. * @param int $subscriberId
  370. *
  371. * @return array/bool
  372. */
  373. public function deleteDevice($subscriberId, $deviceId) {
  374. $result = false;
  375. if ($this->isValidSubscriber($subscriberId)) {
  376. $userLogin = $this->getSubscriberLogin($subscriberId);
  377. $result = $this->api->delete('objects/' . $subscriberId . '/devices/' . $deviceId);
  378. log_register('PTV DEVICE DELETE SUB (' . $userLogin . ') AS [' . $subscriberId . ']');
  379. }
  380. return($result);
  381. }
  382. /**
  383. * Deletes some subscriber`s playlist
  384. *
  385. * @param int $subscriberId
  386. * @param string $playListId
  387. *
  388. * @return void
  389. */
  390. public function deletePlaylist($subscriberId, $playListId) {
  391. if ($this->isValidSubscriber($subscriberId)) {
  392. $userLogin = $this->getSubscriberLogin($subscriberId);
  393. $this->api->delete('/objects/' . $subscriberId . '/playlists/' . $playListId);
  394. log_register('PTV PLAYLIST DELETE SUB (' . $userLogin . ') AS [' . $subscriberId . ']');
  395. }
  396. }
  397. /**
  398. * Renders available subscribers JSON list
  399. *
  400. * @return void
  401. */
  402. public function renderSubsribersAjReply() {
  403. $json = new wf_JqDtHelper();
  404. if (!empty($this->allSubscribers)) {
  405. foreach ($this->allSubscribers as $userLogin => $eachSub) {
  406. if (isset($this->allUserData[$userLogin])) {
  407. $data[] = $eachSub['subscriberid'];
  408. $data[] = $eachSub['date'];
  409. $userAddress = @$this->allUserData[$userLogin]['fulladress'];
  410. $userRealName = @$this->allUserData[$userLogin]['realname'];
  411. $profileLink = wf_Link(self::URL_USERPROFILE . $userLogin, web_profile_icon());
  412. $subViewUrl = self::URL_ME . '&' . self::ROUTE_SUBVIEW . '=' . $userLogin;
  413. $actLinks = wf_Link($subViewUrl, web_edit_icon());
  414. $data[] = $profileLink . ' ' . $userAddress;
  415. $data[] = $userRealName;
  416. $data[] = $actLinks;
  417. $json->addRow($data);
  418. unset($data);
  419. }
  420. }
  421. }
  422. $json->getJson();
  423. }
  424. /**
  425. * Renders existing subscribers list container
  426. *
  427. * @return string
  428. */
  429. public function renderSubscribersList() {
  430. $result = '';
  431. $columns = array('ID', 'Date', 'Address', 'Real Name', 'Actions');
  432. $opts = '"order": [[ 1, "desc" ]]';
  433. $result .= wf_JqDtLoader($columns, self::URL_ME . '&' . self::ROUTE_SUBAJ . '=true', false, __('Subscriptions'), 50, $opts);
  434. return($result);
  435. }
  436. /**
  437. * Renders subscriber services
  438. *
  439. * @param array $subData
  440. *
  441. * @return string
  442. */
  443. protected function renderServices($subData) {
  444. $result = '';
  445. if (!empty($subData['services'])) {
  446. foreach ($subData['services'] as $io => $each) {
  447. $tariffLabel = '';
  448. if (isset($this->allTariffs[$each['id']])) {
  449. $tariffLabel = $this->allTariffs[$each['id']]['name'];
  450. } else {
  451. $tariffLabel = $each['id'];
  452. }
  453. $result .= $tariffLabel . ' ';
  454. }
  455. } else {
  456. $result .= __('No tariff');
  457. }
  458. return($result);
  459. }
  460. /**
  461. * Renders basic subscriber profile
  462. *
  463. * @param string $userLogin
  464. *
  465. * @return string
  466. */
  467. public function renderSubscriber($userLogin) {
  468. $result = '';
  469. if (isset($this->allUserData[$userLogin])) {
  470. if (isset($this->allSubscribers[$userLogin])) {
  471. $subscriberId = $this->allSubscribers[$userLogin]['subscriberid'];
  472. $subData = $this->getUserData($userLogin);
  473. $userData = $this->allUserData[$userLogin];
  474. $subProfileUrl = self::URL_ME . '&' . self::ROUTE_SUBVIEW . '=' . $userLogin;
  475. if ($subData != false) {
  476. $cells = wf_TableCell(__('Address'), '', 'row2');
  477. $cells .= wf_TableCell(wf_Link(self::URL_USERPROFILE . $userLogin, web_profile_icon() . ' ' . $userData['fulladress']));
  478. $rows = wf_TableRow($cells, 'row3');
  479. $cells = wf_TableCell(__('ID'), '30%', 'row2');
  480. $cells .= wf_TableCell($subData['id']);
  481. $rows .= wf_TableRow($cells, 'row3');
  482. $cells = wf_TableCell(__('Cash'), '', 'row2');
  483. $cells .= wf_TableCell($userData['Cash']);
  484. $rows .= wf_TableRow($cells, 'row3');
  485. $cells = wf_TableCell(__('Credit'), '', 'row2');
  486. $cells .= wf_TableCell($userData['Credit']);
  487. $rows .= wf_TableRow($cells, 'row3');
  488. $cells = wf_TableCell(__('IP'), '', 'row2');
  489. $cells .= wf_TableCell($userData['ip']);
  490. $rows .= wf_TableRow($cells, 'row3');
  491. $cells = wf_TableCell(__('Status'), '', 'row2');
  492. $actLed = ($this->allSubscribers[$userLogin]['active']) ? wf_img_sized('skins/icon_active.gif', '', 10) : wf_img_sized('skins/icon_inactive.gif', '', 10);
  493. $cells .= wf_TableCell($actLed . ' ' . __($subData['status']));
  494. $rows .= wf_TableRow($cells, 'row3');
  495. $cells = wf_TableCell(__('Profile') . ' ' . __('EBS'), '', 'row2');
  496. $cells .= wf_TableCell(wf_Link($subData['ebs_url'], wf_img('skins/arrow_right_green.png') . ' ' . __('Show'), false, '', self::NEW_WINDOW));
  497. $rows .= wf_TableRow($cells, 'row3');
  498. $cells = wf_TableCell(__('Date'), '', 'row2');
  499. $cells .= wf_TableCell($subData['date_create']);
  500. $rows .= wf_TableRow($cells, 'row3');
  501. $cells = wf_TableCell(__('Tariffs'), '', 'row2');
  502. $cells .= wf_TableCell($this->renderServices($subData));
  503. $rows .= wf_TableRow($cells, 'row3');
  504. $result .= wf_TableBody($rows, '100%', 0, '');
  505. //append playlists
  506. $result .= $this->renderPlaylists($subData);
  507. //append devices
  508. $result .= $this->renderDevices($subData);
  509. //some user controls here
  510. $result .= wf_delimiter(0);
  511. $result .= $this->renderSubscriberControls($subscriberId, $subData);
  512. } else {
  513. $result .= $this->messages->getStyledMessage(__('Something went wrong') . ': ' . __('Empty reply received'), 'error');
  514. }
  515. } else {
  516. $result .= $this->messages->getStyledMessage(__('Something went wrong') . ': EX_SUBSCRIBER_NOT_EXISTS', 'error');
  517. }
  518. } else {
  519. $result .= $this->messages->getStyledMessage(__('Something went wrong') . ': ' . __('User not exists'), 'error');
  520. }
  521. return($result);
  522. }
  523. /**
  524. * Renders devices of some subscriber
  525. *
  526. * @param array $subData
  527. *
  528. * @return string
  529. */
  530. protected function renderDevices($subData) {
  531. $result = '';
  532. if (!empty($subData['devices'])) {
  533. $subscriberId = $subData['id'];
  534. $userLogin = $this->getSubscriberLogin($subscriberId);
  535. $subProfileUrl = self::URL_ME . '&' . self::ROUTE_SUBVIEW . '=' . $userLogin;
  536. $cells = wf_TableCell(__('ID'));
  537. $cells .= wf_TableCell(__('Created'));
  538. $cells .= wf_TableCell(__('Updated'));
  539. $cells .= wf_TableCell(__('Login'));
  540. $cells .= wf_TableCell(__('Password'));
  541. $cells .= wf_TableCell(__('Device'));
  542. $cells .= wf_TableCell(__('IP'));
  543. $cells .= wf_TableCell(__('Actions'));
  544. $rows = wf_TableRow($cells, 'row1');
  545. foreach ($subData['devices'] as $io => $eachDevice) {
  546. $cells = wf_TableCell($eachDevice['id']);
  547. $cells .= wf_TableCell($eachDevice['created']);
  548. $cells .= wf_TableCell($eachDevice['updated']);
  549. $cells .= wf_TableCell($eachDevice['login']);
  550. $cells .= wf_TableCell($eachDevice['password']);
  551. $cells .= wf_TableCell($eachDevice['device']);
  552. $cells .= wf_TableCell($eachDevice['ip']);
  553. $devDelUrl = self::URL_ME . '&' . self::ROUTE_DEVDEL . '=' . $eachDevice['id'] . '&' . self::ROUTE_SUBID . '=' . $subscriberId;
  554. $devDelControls = wf_ConfirmDialog($devDelUrl, web_delete_icon() . ' ' . __('Delete'), $this->messages->getDeleteAlert(), '', $subProfileUrl);
  555. $cells .= wf_TableCell($devDelControls);
  556. $rows .= wf_TableRow($cells, 'row5');
  557. }
  558. $result .= wf_tag('b') . __('Devices') . wf_tag('b', true) . wf_delimiter(0);
  559. $result .= wf_TableBody($rows, '100%', 0, '');
  560. } else {
  561. $result .= $this->messages->getStyledMessage(__('This user have no any devices'), 'warning');
  562. }
  563. return($result);
  564. }
  565. /**
  566. * Renders playlists of some subscriber
  567. *
  568. * @param array $subData
  569. *
  570. * @return string
  571. */
  572. protected function renderPlaylists($subData) {
  573. $result = '';
  574. if (!empty($subData['playlists'])) {
  575. $subscriberId = $subData['id'];
  576. $userLogin = $this->getSubscriberLogin($subscriberId);
  577. $subProfileUrl = self::URL_ME . '&' . self::ROUTE_SUBVIEW . '=' . $userLogin;
  578. $cells = wf_TableCell(__('ID'));
  579. $cells .= wf_TableCell(__('Created'));
  580. $cells .= wf_TableCell(__('Updated'));
  581. $cells .= wf_TableCell(__('Genres'));
  582. $cells .= wf_TableCell(__('TV guide'));
  583. $cells .= wf_TableCell(__('IP'));
  584. $cells .= wf_TableCell(__('URL'));
  585. $cells .= wf_TableCell(__('Device'));
  586. $cells .= wf_TableCell(__('Actions'));
  587. $rows = wf_TableRow($cells, 'row1');
  588. foreach ($subData['playlists'] as $io => $eachPlaylist) {
  589. $cells = wf_TableCell($eachPlaylist['id']);
  590. $cells .= wf_TableCell($eachPlaylist['created']);
  591. $cells .= wf_TableCell($eachPlaylist['updated']);
  592. $cells .= wf_TableCell(web_bool_led($eachPlaylist['genres']));
  593. $cells .= wf_TableCell(web_bool_led($eachPlaylist['tv_guide']));
  594. $cells .= wf_TableCell($eachPlaylist['ip']);
  595. $urlControls = wf_Link($eachPlaylist['url'], $eachPlaylist['url'], false, '', self::NEW_WINDOW);
  596. $cells .= wf_TableCell($urlControls);
  597. $cells .= wf_TableCell($eachPlaylist['device_id']);
  598. $plDeleteUrl = self::URL_ME . '&' . self::ROUTE_PLDEL . '=' . $eachPlaylist['id'] . '&' . self::ROUTE_SUBID . '=' . $subscriberId;
  599. $plDelControls = wf_ConfirmDialog($plDeleteUrl, web_delete_icon() . ' ' . __('Delete'), $this->messages->getDeleteAlert(), '', $subProfileUrl);
  600. $cells .= wf_TableCell($plDelControls);
  601. $rows .= wf_TableRow($cells, 'row5');
  602. }
  603. $result .= wf_tag('b') . __('Playlists') . wf_tag('b', true) . wf_delimiter(0);
  604. $result .= wf_TableBody($rows, '100%', 0, '');
  605. } else {
  606. $result .= $this->messages->getStyledMessage(__('This user have no any playlists'), 'warning');
  607. }
  608. return($result);
  609. }
  610. /**
  611. * Renders users tariff change form
  612. *
  613. * @param int $subscriberId
  614. *
  615. * @return string
  616. */
  617. protected function renderUserTariffEditForm($subscriberId) {
  618. $result = '';
  619. if (!empty($this->allTariffs)) {
  620. $mainTariffsArr = array();
  621. $additionalTariffsArr = array();
  622. $userLogin = $this->getSubscriberLogin($subscriberId);
  623. $currentMainTariff = $this->allSubscribers[$userLogin]['maintariff'];
  624. foreach ($this->allTariffs as $io => $each) {
  625. if ($each['main']) {
  626. $mainTariffsArr[$each['serviceid']] = $each['name'];
  627. } else {
  628. $additionalTariffsArr[$each['serviceid']] = $each['name'];
  629. }
  630. }
  631. if (!empty($mainTariffsArr)) {
  632. $inputs = wf_HiddenInput(self::PROUTE_TARIFFEDITSUBID, $subscriberId);
  633. $inputs .= wf_Selector(self::PROUTE_SETMAINTARIFFID, $mainTariffsArr, __('Primary') . ' ' . __('Tariff'), $currentMainTariff, true);
  634. $inputs .= wf_Submit(__('Save'));
  635. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  636. }
  637. } else {
  638. $result .= $this->messages->getStyledMessage(__('Tariffs') . ': ' . __('Not exists'), 'error');
  639. }
  640. return($result);
  641. }
  642. /**
  643. * Sets primary tariff for some subscriber
  644. *
  645. * @param int $subscriberId
  646. * @param int $tariffId
  647. *
  648. * @return void
  649. */
  650. public function setMainTariff($subscriberId, $tariffId) {
  651. $tariffId = ubRouting::filters($tariffId, 'int');
  652. $subscriberId = ubRouting::filters($subscriberId, 'int');
  653. if ($this->isValidSubscriber($subscriberId)) {
  654. $userLogin = $this->getSubscriberLogin($subscriberId);
  655. $currentTariff = $this->allSubscribers[$userLogin]['maintariff'];
  656. //deleting old service if required
  657. if ($currentTariff) {
  658. if ($currentTariff != $tariffId) {
  659. $this->api->delete('/objects/' . $subscriberId . '/services/' . $currentTariff);
  660. log_register('PTV SUB (' . $userLogin . ') UNSET TARIFF [' . $currentTariff . '] AS [' . $subscriberId . ']');
  661. }
  662. }
  663. if ($currentTariff != $tariffId) {
  664. //database update
  665. $this->subscribersDb->data('maintariff', $tariffId);
  666. $this->subscribersDb->data('active', 1);
  667. $this->subscribersDb->where('subscriberid', '=', $subscriberId);
  668. $this->subscribersDb->save();
  669. //push to service API
  670. $this->api->post('/objects/' . $subscriberId . '/services', array('id' => $tariffId, 'auto_renewal' => 1));
  671. //put log record
  672. log_register('PTV SUB (' . $userLogin . ') SET TARIFF [' . $tariffId . '] AS [' . $subscriberId . ']');
  673. }
  674. }
  675. }
  676. /**
  677. * Returns some subscriber controls
  678. *
  679. * @param int $subscriberId
  680. * @param array $subData
  681. *
  682. * @return string
  683. */
  684. protected function renderSubscriberControls($subscriberId, $subData = array()) {
  685. $result = '';
  686. if ($this->isValidSubscriber($subscriberId)) {
  687. $userLogin = $this->getSubscriberLogin($subscriberId);
  688. $plCreateUrl = self::URL_ME . '&' . self::ROUTE_PLCREATE . '=' . $subscriberId;
  689. $subProfileUrl = self::URL_ME . '&' . self::ROUTE_SUBVIEW . '=' . $userLogin;
  690. $plCreateLabel = web_icon_create() . ' ' . __('Just create new playlist');
  691. $result .= wf_ConfirmDialog($plCreateUrl, $plCreateLabel, __('Just create new playlist') . '? ' . $this->messages->getEditAlert(), 'ubButton', $subProfileUrl) . ' ';
  692. $devCreateUrl = self::URL_ME . '&' . self::ROUTE_DEVCREATE . '=' . $subscriberId;
  693. $devCreateLabel = wf_img('skins/switch_models.png') . ' ' . __('Create new device');
  694. $result .= wf_ConfirmDialog($devCreateUrl, $devCreateLabel, __('Create new device') . '? ' . $this->messages->getEditAlert(), 'ubButton', $subProfileUrl) . ' ';
  695. $result .= wf_modalAuto(wf_img('skins/icon_tariff.gif') . ' ' . __('Edit tariff'), __('Tariff'), $this->renderUserTariffEditForm($subscriberId), 'ubButton');
  696. if (!empty($subData)) {
  697. $userScheme = wf_tag('pre') . print_r($subData, true) . wf_tag('pre', true);
  698. $result .= wf_modal(wf_img('skins/brain.png') . ' ' . __('User inside'), __('User inside'), $userScheme, 'ubButton', '800', '600');
  699. }
  700. }
  701. return($result);
  702. }
  703. /**
  704. * Renders basic user registration form
  705. *
  706. * @return string
  707. */
  708. protected function renderUserRegisterForm() {
  709. $result = '';
  710. $inputs = wf_TextInput(self::PROUTE_SUBREG, __('Login'), '', false, 20);
  711. $inputs .= wf_Submit(__('Register'));
  712. $result .= wf_Form("", 'POST', $inputs, 'glamour');
  713. return($result);
  714. }
  715. /**
  716. * Renders primary module controls
  717. *
  718. * @return string
  719. */
  720. public function renderPanel() {
  721. $result = '';
  722. $result .= wf_modalAuto(web_icon_create() . ' ' . __('Users registration'), __('Users registration'), $this->renderUserRegisterForm(), 'ubButton');
  723. $result .= wf_Link(self::URL_ME . '&' . self::ROUTE_SUBLIST . '=true', wf_img('skins/ukv/users.png') . ' ' . __('Subscriptions'), false, 'ubButton') . ' ';
  724. $result .= wf_Link(self::URL_ME . '&' . self::ROUTE_TARIFFS . '=true', wf_img('skins/ukv/dollar.png') . ' ' . __('Tariffs'), false, 'ubButton') . ' ';
  725. return($result);
  726. }
  727. /**
  728. * Renders bundles (server side tariffs) available at service
  729. *
  730. * @return string
  731. */
  732. public function renderBundles() {
  733. $result = '';
  734. $raw = $this->api->get('/search/bundles');
  735. if ($raw) {
  736. if (isset($raw['bundles'])) {
  737. $cells = wf_TableCell(__('Service ID'));
  738. $cells .= wf_TableCell(__('Name') . ' ' . __('UA'));
  739. $cells .= wf_TableCell(__('Name') . ' ' . __('RU'));
  740. $cells .= wf_TableCell(__('Primary'));
  741. $cells .= wf_TableCell(__('Channels'));
  742. $cells .= wf_TableCell(__('Price'));
  743. $rows = wf_TableRow($cells, 'row1');
  744. foreach ($raw['bundles'] as $io => $each) {
  745. $cells = wf_TableCell($each['service_id']);
  746. $cells .= wf_TableCell($each['name_uk']);
  747. $cells .= wf_TableCell($each['name_ru']);
  748. $cells .= wf_TableCell(web_bool_led($each['main']));
  749. $cells .= wf_TableCell($each['channels_count']);
  750. $cells .= wf_TableCell($each['cost']);
  751. $rows .= wf_TableRow($cells, 'row5');
  752. }
  753. $result .= wf_TableBody($rows, '100%', 0, 'sortable');
  754. }
  755. } else {
  756. $result .= $this->messages->getStyledMessage(__('Something went wrong') . ': ' . __('Tariffs offered') . ' ' . __('Not exists'), 'error');
  757. }
  758. return($result);
  759. }
  760. /**
  761. * Renders new tariff creation form
  762. *
  763. * @return string
  764. */
  765. protected function renderTariffCreateForm() {
  766. $result = '';
  767. $sup = wf_tag('sup') . '*' . wf_tag('sup', true);
  768. $inputs = wf_TextInput(self::PROUTE_CREATETARIFFID, __('Service ID') . $sup, '', true, 5, 'digits');
  769. $inputs .= wf_TextInput(self::PROUTE_CREATETARIFFNAME, __('Tariff name') . $sup, '', true, 20);
  770. $inputs .= wf_CheckInput(self::PROUTE_CREATETARIFFMAIN, __('Primary'), true, true);
  771. $inputs .= wf_TextInput(self::PROUTE_CREATETARIFFCHANS, __('Description'), '', true, 20);
  772. $inputs .= wf_TextInput(self::PROUTE_CREATETARIFFFEE, __('Fee') . $sup, '', true, 4, 'finance');
  773. $inputs .= wf_delimiter(0);
  774. $inputs .= wf_Submit(__('Create'));
  775. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  776. return($result);
  777. }
  778. /**
  779. * Creates new tariff in database
  780. *
  781. * @return void/string on error
  782. */
  783. public function createTariff() {
  784. $result = '';
  785. if (ubRouting::checkPost(array(self::PROUTE_CREATETARIFFNAME, self::PROUTE_CREATETARIFFID))) {
  786. $tariffId = ubRouting::post(self::PROUTE_CREATETARIFFID, 'int');
  787. $tariffName = ubRouting::post(self::PROUTE_CREATETARIFFNAME, 'mres');
  788. $tariffMain = (ubRouting::checkPost(self::PROUTE_CREATETARIFFMAIN)) ? 1 : 0;
  789. $tariffChans = ubRouting::post(self::PROUTE_CREATETARIFFCHANS, 'mres');
  790. $tariffFee = ubRouting::post(self::PROUTE_CREATETARIFFFEE);
  791. if ($tariffId) {
  792. if (!isset($this->allTariffs[$tariffId])) {
  793. if ($tariffName) {
  794. if (zb_checkMoney($tariffFee)) {
  795. $this->tariffsDb->data('serviceid', $tariffId);
  796. $this->tariffsDb->data('main', $tariffMain);
  797. $this->tariffsDb->data('name', $tariffName);
  798. $this->tariffsDb->data('chans', $tariffChans);
  799. $this->tariffsDb->data('fee', $tariffFee);
  800. $this->tariffsDb->create();
  801. log_register('PTV TARIFF CREATE `' . $tariffName . '` AS [' . $tariffId . '] FEE `' . $tariffFee . '`');
  802. } else {
  803. $result .= __('Wrong format of money sum');
  804. }
  805. } else {
  806. $result .= __('Wrong tariff name');
  807. }
  808. } else {
  809. $result .= __('Duplicate element ID');
  810. log_register('PTV TARIFF CREATE `' . $tariffName . '` AS [' . $tariffId . '] DUPLICATE FAIL');
  811. }
  812. } else {
  813. $result .= __('Wrong tariff id');
  814. }
  815. }
  816. return($result);
  817. }
  818. /**
  819. * Deletes existing tariff from database
  820. *
  821. * @param int $tariffId
  822. *
  823. * @return void/string on error
  824. */
  825. public function deleteTariff($tariffId) {
  826. $result = '';
  827. $tariffId = ubRouting::filters($tariffId, 'int');
  828. if (isset($this->allTariffs[$tariffId])) {
  829. if ($this->isTariffProtected($tariffId)) {
  830. $result = __('Tariff is used by some users');
  831. } else {
  832. $tariffData = $this->allTariffs[$tariffId];
  833. $tariffName = $tariffData['name'];
  834. $tariffFee = $tariffData['fee'];
  835. $this->tariffsDb->where('serviceid', '=', $tariffId);
  836. $this->tariffsDb->delete();
  837. log_register('PTV TARIFF DELETE `' . $tariffName . '` AS [' . $tariffId . '] FEE `' . $tariffFee . '`');
  838. }
  839. } else {
  840. $result .= __('Tariff not exists');
  841. }
  842. return($result);
  843. }
  844. /**
  845. * Checks is some tariff protected of usage by some user
  846. *
  847. * @param int $tariffId
  848. *
  849. * @return bool
  850. */
  851. protected function isTariffProtected($tariffId) {
  852. $result = false;
  853. if (!empty($this->allSubscribers)) {
  854. foreach ($this->allSubscribers as $io => $each) {
  855. if ($each['maintariff'] == $tariffId) {
  856. $result = true;
  857. }
  858. if (ispos($each['addtariffs'], $tariffId)) {
  859. $result = true;
  860. }
  861. }
  862. }
  863. return($result);
  864. }
  865. /**
  866. * Renders list of tariffs available for users
  867. *
  868. * @return string
  869. */
  870. public function renderTariffs() {
  871. $result = '';
  872. $result .= wf_modalAuto(web_add_icon() . ' ' . __('Create new tariff'), __('Create new tariff'), $this->renderTariffCreateForm(), 'ubButton');
  873. $result .= wf_Link(self::URL_ME . '&' . self::ROUTE_BUNDLES . '=true', wf_img('skins/tariffinfo.gif') . ' ' . __('Available tariffs'), false, 'ubButton');
  874. $result .= wf_delimiter();
  875. if (!empty($this->allTariffs)) {
  876. $cells = wf_TableCell(__('Service ID'));
  877. $cells .= wf_TableCell(__('Name'));
  878. $cells .= wf_TableCell(__('Primary'));
  879. $cells .= wf_TableCell(__('Description'));
  880. $cells .= wf_TableCell(__('Fee'));
  881. $cells .= wf_TableCell(__('Actions'));
  882. $rows = wf_TableRow($cells, 'row1');
  883. foreach ($this->allTariffs as $io => $each) {
  884. $cells = wf_TableCell($each['serviceid']);
  885. $cells .= wf_TableCell($each['name']);
  886. $cells .= wf_TableCell(web_bool_led($each['main']));
  887. $cells .= wf_TableCell($each['chans']);
  888. $cells .= wf_TableCell($each['fee']);
  889. $tariffsCancelUrl = self::URL_ME . '&' . self::ROUTE_TARIFFS . '=true';
  890. $tariffsDeleteUrl = self::URL_ME . '&' . self::ROUTE_TARDEL . '=' . $each['serviceid'];
  891. $tariffControls = wf_ConfirmDialog($tariffsDeleteUrl, web_delete_icon() . ' ' . __('Delete'), $this->messages->getDeleteAlert(), '', $tariffsCancelUrl);
  892. $cells .= wf_TableCell($tariffControls);
  893. $rows .= wf_TableRow($cells, 'row5');
  894. }
  895. $result .= wf_TableBody($rows, '100%', 0, 'sortable');
  896. } else {
  897. $result .= $this->messages->getStyledMessage(__('Nothing to show'), 'warning');
  898. }
  899. return($result);
  900. }
  901. /**
  902. * Charges some tariff fee from user account
  903. *
  904. * @param string $userLogin
  905. * @param int $tariffId
  906. *
  907. * @return void
  908. */
  909. public function chargeUserFee($userLogin, $tariffId) {
  910. if (isset($this->allUserData[$userLogin])) {
  911. if (isset($this->allTariffs[$tariffId])) {
  912. $subscriberId = $this->getSubscriberId($userLogin);
  913. $tariffFee = $this->allTariffs[$tariffId]['fee'];
  914. zb_CashAdd($userLogin, '-' . $tariffFee, 'add', 1, 'PROSTOTV:' . $tariffId);
  915. log_register('PTV CHARGE TARIFF [' . $tariffId . '] FEE `' . $tariffFee . '` FOR (' . $userLogin . ') AS [' . $subscriberId . ']');
  916. } else {
  917. log_register('PTV CHARGE FAIL NOTARIFF [' . $tariffId . '] FOR (' . $userLogin . ') AS [' . $subscriberId . ']');
  918. }
  919. } else {
  920. log_register('PTV CHARGE FAIL NOUSER (' . $userLogin . ')');
  921. }
  922. }
  923. /**
  924. * Performs fee processing of all registered subscribers
  925. *
  926. * @return void
  927. */
  928. public function feeProcessing() {
  929. if (!empty($this->allSubscribers)) {
  930. foreach ($this->allSubscribers as $io => $eachSub) {
  931. $userLogin = $eachSub['login'];
  932. $subscriberId = $eachSub['subscriberid'];
  933. $userFee = 0;
  934. if (isset($this->allUserData[$userLogin])) {
  935. $userCash = $this->allUserData[$userLogin]['Cash'];
  936. //user subscription is active now
  937. if ($eachSub['active']) {
  938. $this->chargeUserFee($eachSub['login'], $eachSub['maintariff']);
  939. }
  940. } else {
  941. log_register('PTV CHARGE (' . $userLogin . ') AS [' . $eachSub . '] FAIL MISS');
  942. }
  943. }
  944. }
  945. }
  946. /**
  947. * Renders JSON reply for some userstats frontend requests
  948. *
  949. * @param array $reply
  950. *
  951. * @return void
  952. */
  953. protected function jsonRenderReply($reply) {
  954. $reply = json_encode($reply);
  955. die($reply);
  956. }
  957. /**
  958. * Renders user subscription data for some login
  959. *
  960. * @param string $userLogin
  961. *
  962. * @return void
  963. */
  964. public function usReplyUserData($userLogin) {
  965. $reply = array();
  966. if (isset($this->allSubscribers[$userLogin])) {
  967. $reply = $this->allSubscribers[$userLogin];
  968. }
  969. $this->jsonRenderReply($reply);
  970. }
  971. /**
  972. * Renders subscriber full data
  973. *
  974. * @param string $userLogin
  975. *
  976. * @return void
  977. */
  978. public function usReplyUserFullData($userLogin) {
  979. $reply = array();
  980. $reply = $this->getUserData($userLogin);
  981. $this->jsonRenderReply($reply);
  982. }
  983. /**
  984. * Renders available tariffs list
  985. *
  986. * @return void
  987. */
  988. public function usReplyTariffs() {
  989. $reply = array();
  990. if (!empty($this->allTariffs)) {
  991. //TODO: support of additional tariffs
  992. foreach ($this->allTariffs as $io => $each) {
  993. if ($each['main']) {
  994. $reply[$io] = $each;
  995. }
  996. }
  997. }
  998. $this->jsonRenderReply($reply);
  999. }
  1000. /**
  1001. * Just deactivates service fro user account
  1002. *
  1003. * @param int $subscriberId
  1004. * @param int $tariffId
  1005. *
  1006. * @return void
  1007. */
  1008. public function usUnsubscribe($subscriberId, $tariffId) {
  1009. $reply = array();
  1010. $userLogin = $this->getSubscriberLogin($subscriberId);
  1011. $this->api->delete('/objects/' . $subscriberId . '/services/' . $tariffId);
  1012. $this->subscribersDb->data('active', '0');
  1013. $this->subscribersDb->data('maintariff', '0');
  1014. $this->subscribersDb->where('subscriberid', '=', $subscriberId);
  1015. $this->subscribersDb->save();
  1016. log_register('PTV SUB (' . $userLogin . ') UNSET TARIFF [' . $tariffId . '] AS [' . $subscriberId . ']');
  1017. $this->jsonRenderReply($reply);
  1018. }
  1019. /**
  1020. * Subscribes user to some service
  1021. *
  1022. * @param string $subscriberId
  1023. * @param int $tariffId
  1024. *
  1025. * @return void
  1026. */
  1027. public function usSubscribe($userLogin, $tariffId) {
  1028. if (isset($this->allTariffs[$tariffId])) {
  1029. //may be thats new user?
  1030. $subscriberId = $this->getSubscriberId($userLogin);
  1031. if (!$this->isValidSubscriber($subscriberId)) {
  1032. $this->userRegister($userLogin);
  1033. //update subscriberId
  1034. $this->loadSubscribers();
  1035. $subscriberId = $this->getSubscriberId($userLogin);
  1036. }
  1037. //just switch tariff
  1038. if ($this->isValidSubscriber($subscriberId)) {
  1039. $this->setMainTariff($subscriberId, $tariffId);
  1040. }
  1041. //charge tariff fee after
  1042. $this->chargeUserFee($userLogin, $tariffId);
  1043. }
  1044. }
  1045. }