api.asterisk.php 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225
  1. <?php
  2. /**
  3. * Asterisk PBX basic integration class
  4. */
  5. class Asterisk {
  6. /**
  7. * Contains Ubstorage data for Asterisk as key=>value
  8. *
  9. * @var array
  10. */
  11. protected $config = array();
  12. /**
  13. * Contains Ubstorage data for Number Alias Asterisk as key=>value
  14. *
  15. * @var array
  16. */
  17. protected $NumAliases = array();
  18. /**
  19. * Contains Login and mobiles from MySQL Databases as login=>data
  20. *
  21. * @var array
  22. */
  23. protected $result_LoginByNumber;
  24. /**
  25. * Contains mobiles and Login from MySQL Databases as Number=>Login
  26. *
  27. * @var array
  28. */
  29. protected $result_NumberLogin;
  30. /**
  31. * Contains only unniq mobiles and Login from MySQL Databases as Number=>Login
  32. *
  33. * @var array
  34. */
  35. protected $result_NumberLoginUniq;
  36. /**
  37. *
  38. *
  39. * @var array
  40. */
  41. protected $allrealnames;
  42. /**
  43. *
  44. *
  45. * @var array
  46. */
  47. protected $alladdress;
  48. /**
  49. * Contains system mussages object placeholder
  50. *
  51. * @var object
  52. */
  53. protected $messages = '';
  54. /**
  55. * Comments caching time
  56. *
  57. * @var int
  58. */
  59. protected $cacheTime = ''; //month by default
  60. /**
  61. * System alter.ini config as key=>value
  62. *
  63. * @var array
  64. */
  65. protected $altCfg = array();
  66. /**
  67. * Contains default recorded calls path
  68. *
  69. * @var string
  70. */
  71. protected $recordingsPath = '';
  72. /**
  73. * Determines whether to use CEL table and contains CEL table name
  74. *
  75. * @var bool
  76. */
  77. protected $recordingsCELTab = '';
  78. /**
  79. * Contains default recorded files file extensions
  80. *
  81. * @var string
  82. */
  83. protected $recordingsFormat = '';
  84. /**
  85. * Placeholder for ASTERISK_GET_FULL_CDR_CEL_DATA alter.ini option
  86. *
  87. * @var bool
  88. */
  89. protected $getFullCDRCELData = false;
  90. /**
  91. * Placeholder for MOBILES_EXT alter.ini option
  92. *
  93. * @var bool
  94. */
  95. protected $extMobilesON = false;
  96. // Database's vars:
  97. private $connected;
  98. private $AsteriskDB;
  99. const URL_ME = '?module=asterisk';
  100. const CACHE_PATH = 'exports/';
  101. public function __construct() {
  102. $this->loadAlter();
  103. $this->initMessages();
  104. $this->AsteriskLoadConf();
  105. $this->AsteriskLoadNumAliases();
  106. $this->AsteriskConnectDB();
  107. $this->initCache();
  108. }
  109. /**
  110. * Loads system alter config into private property for further usage
  111. *
  112. * @global object $ubillingConfig
  113. *
  114. * @return void
  115. */
  116. protected function loadAlter() {
  117. global $ubillingConfig;
  118. $this->altCfg = $ubillingConfig->getAlter();
  119. $this->recordingsPath = ($ubillingConfig->getAlterParam('ASTERISK_CALLRECS_PATH')) ? $ubillingConfig->getAlterParam('ASTERISK_CALLRECS_PATH') : '';
  120. $this->recordingsCELTab = ($ubillingConfig->getAlterParam('ASTERISK_CALLRECS_CEL_TAB_NAME')) ? $ubillingConfig->getAlterParam('ASTERISK_CALLRECS_CEL_TAB_NAME') : '';
  121. $this->recordingsFormat = ($ubillingConfig->getAlterParam('ASTERISK_CALLRECS_FORMAT')) ? $ubillingConfig->getAlterParam('ASTERISK_CALLRECS_FORMAT') : '';
  122. $this->getFullCDRCELData = $ubillingConfig->getAlterParam('ASTERISK_GET_FULL_CDR_CEL_DATA');
  123. $this->extMobilesON = $ubillingConfig->getAlterParam('MOBILES_EXT');
  124. }
  125. /**
  126. * Load Asterisk config
  127. *
  128. * @return array
  129. */
  130. protected function AsteriskLoadConf() {
  131. $this->config = $this->AsteriskGetConf();
  132. $this->cacheTime = $this->config['cachetime'];
  133. }
  134. /**
  135. * Inits system messages helper object for further usage
  136. *
  137. * @return void
  138. */
  139. protected function initMessages() {
  140. $this->messages = new UbillingMessageHelper();
  141. }
  142. /**
  143. * Initalizes system cache object for further usage
  144. *
  145. * @return void
  146. */
  147. protected function initCache() {
  148. $this->cache = new UbillingCache();
  149. }
  150. /**
  151. * Check for last cache data and if need clean
  152. *
  153. * @return void
  154. */
  155. protected function AsterikCacheInfoClean($asteriskTable, $from, $to) {
  156. if (!empty($from) and ! empty($to)) {
  157. $query = "select uniqueid from `" . $asteriskTable . "` where `calldate` BETWEEN '" . $from . " 00:00:00' AND '" . $to . " 23:59:59' AND (`lastapp`='dial' OR `lastapp`='queue') ORDER BY `calldate` DESC LIMIT 1";
  158. $cacheName = $from . $to;
  159. $cache_uniqueid_key = 'ASTERISK_UNI_' . $cacheName;
  160. $last_db_uniqueid = $this->AsteriskQuery($query);
  161. $last_cache_uniqueid = $this->cache->get($cache_uniqueid_key, $this->cacheTime);
  162. // Если `uniqueid` не равен записи в кеше, то очищаем весь кеш
  163. if (($uniqueid = @$last_db_uniqueid['0']['uniqueid']) != $last_cache_uniqueid) {
  164. $this->cache->delete('ASTERISK_CDR_' . $cacheName, $this->cacheTime);
  165. $this->cache->set($cache_uniqueid_key, $uniqueid, $this->cacheTime);
  166. }
  167. }
  168. }
  169. /**
  170. * Gets Asterisk config from DB, or sets default values
  171. *
  172. * @return array
  173. */
  174. protected function AsteriskGetConf() {
  175. $result = array();
  176. //getting url
  177. $host = zb_StorageGet('ASTERISK_HOST');
  178. if (empty($host)) {
  179. $host = 'localhost';
  180. zb_StorageSet('ASTERISK_HOST', $host);
  181. }
  182. //getting login
  183. $login = zb_StorageGet('ASTERISK_LOGIN');
  184. if (empty($login)) {
  185. $login = 'asterisk';
  186. zb_StorageSet('ASTERISK_LOGIN', $login);
  187. }
  188. //getting DB name
  189. $db = zb_StorageGet('ASTERISK_DB');
  190. if (empty($db)) {
  191. $db = 'asteriskdb';
  192. zb_StorageSet('ASTERISK_DB', $db);
  193. }
  194. //getting CDR table name
  195. $table = zb_StorageGet('ASTERISK_TABLE');
  196. if (empty($table)) {
  197. $table = 'cdr';
  198. zb_StorageSet('ASTERISK_TABLE', $table);
  199. }
  200. //getting password
  201. $password = zb_StorageGet('ASTERISK_PASSWORD');
  202. if (empty($password)) {
  203. $password = 'password';
  204. zb_StorageSet('ASTERISK_PASSWORD', $password);
  205. }
  206. //getting caching time
  207. $cache = zb_StorageGet('ASTERISK_CACHETIME');
  208. if (empty($cache)) {
  209. $cache = '2592000';
  210. zb_StorageSet('ASTERISK_CACHETIME', $cache);
  211. }
  212. //getting caching time
  213. $dopmobile = zb_StorageGet('ASTERISK_DOPMOBILE');
  214. if (empty($dopmobile)) {
  215. $dopmobile = '';
  216. zb_StorageSet('ASTERISK_DOPMOBILE', $dopmobile);
  217. }
  218. $result['host'] = $host;
  219. $result['db'] = $db;
  220. $result['table'] = $table;
  221. $result['login'] = $login;
  222. $result['password'] = $password;
  223. $result['cachetime'] = $cache;
  224. $result['dopmobile'] = $dopmobile;
  225. return ($result);
  226. }
  227. /**
  228. * Initialises connection with Asterisk database server and selects needed db
  229. *
  230. * @param MySQL Connection Id $connection
  231. * @return MySQLDB
  232. */
  233. protected function AsteriskConnectDB() {
  234. $this->AsteriskDB = new mysqli($this->config['host'], $this->config['login'], $this->config['password'], $this->config['db']);
  235. if (!$this->AsteriskDB->connect_error) {
  236. $this->connected = TRUE;
  237. return $this->connected;
  238. } else {
  239. $this->connected = FALSE;
  240. return $this->connected;
  241. }
  242. }
  243. /**
  244. * Another database query execution
  245. *
  246. * @param string $query - query to execute
  247. *
  248. * @return array
  249. */
  250. public function AsteriskQuery($query) {
  251. if ($this->connected) {
  252. $result = array();
  253. $result_query = $this->AsteriskDB->query($query, MYSQLI_USE_RESULT);
  254. while ($row = $result_query->fetch_assoc()) {
  255. $result[] = $row;
  256. }
  257. mysqli_free_result($result_query);
  258. //$this->AsteriskDB->close();
  259. return ($result);
  260. } else {
  261. $result = rcms_redirect(self::URL_ME . '&config=true');
  262. return ($result);
  263. }
  264. }
  265. /**
  266. * Load numbers aliases
  267. *
  268. * @return array
  269. */
  270. protected function AsteriskLoadNumAliases() {
  271. $this->NumAliases = $this->AsteriskGetNumAliases();
  272. }
  273. /**
  274. * Get numbers aliases from database, or set default empty array
  275. *
  276. * @return array
  277. */
  278. protected function AsteriskGetNumAliases() {
  279. $result = array();
  280. $rawAliases = zb_StorageGet('ASTERISK_NUMALIAS');
  281. if (empty($rawAliases)) {
  282. $newAliasses = serialize($result);
  283. $newAliasses = base64_encode($newAliasses);
  284. zb_StorageSet('ASTERISK_NUMALIAS', $newAliasses);
  285. } else {
  286. $readAlias = base64_decode($rawAliases);
  287. $readAlias = unserialize($readAlias);
  288. $result = $readAlias;
  289. }
  290. return ($result);
  291. }
  292. /**
  293. * Returns Asterisk module configuration form
  294. *
  295. * @return string
  296. */
  297. public function AsteriskConfigForm() {
  298. $result = wf_BackLink(self::URL_ME, '', true);
  299. $result .= wf_tag('br');
  300. if (cfr('ASTERISKCONF')) {
  301. $inputs = '';
  302. if (!$this->connected) {
  303. $inputs .= $this->messages->getStyledMessage(__('Connection error for Asterisk Database'), 'error') . wf_tag('br/', false);
  304. }
  305. $inputs .= wf_TextInput('newhost', __('Asterisk host'), $this->config['host'], true);
  306. $inputs .= wf_TextInput('newdb', __('Database name'), $this->config['db'], true);
  307. $inputs .= wf_TextInput('newtable', __('CDR table name'), $this->config['table'], true);
  308. $inputs .= wf_TextInput('newlogin', __('Database login'), $this->config['login'], true);
  309. $inputs .= wf_TextInput('newpassword', __('Database password'), $this->config['password'], true);
  310. $inputs .= wf_TextInput('newcachetime', __('Cache time'), $this->config['cachetime'], true);
  311. $inputs .= wf_TextInput('dopmobile', __('Additional mobile - Profile field ID'), $this->config['dopmobile'], true);
  312. $inputs .= wf_Submit(__('Save'));
  313. $result .= wf_Form("", "POST", $inputs, 'glamour');
  314. } else {
  315. $result = $this->messages->getStyledMessage(__('Access denied'), 'error');
  316. }
  317. return ($result);
  318. }
  319. /**
  320. * Returns number aliases aka phonebook form
  321. *
  322. * @return string
  323. */
  324. public function AsteriskAliasesForm() {
  325. $result = '';
  326. if (cfr('ASTERISKALIAS')) {
  327. $createinputs = wf_TextInput('newaliasnum', __('Phone'), '', true);
  328. $createinputs .= wf_TextInput('newaliasname', __('Alias'), '', true);
  329. $createinputs .= wf_Submit(__('Create'));
  330. $createform = wf_Form('', 'POST', $createinputs, 'glamour');
  331. $result = $createform;
  332. if (!empty($this->NumAliases)) {
  333. $delArr = array();
  334. foreach ($this->NumAliases as $num => $eachname) {
  335. $delArr[$num] = $num . ' - ' . $eachname;
  336. }
  337. $delinputs = wf_Selector('deletealias', $delArr, __('Delete alias'), '', false);
  338. $delinputs .= wf_Submit(__('Delete'));
  339. $delform = wf_Form('', 'POST', $delinputs, 'glamour');
  340. $result .= $delform;
  341. }
  342. } else {
  343. $result = $this->messages->getStyledMessage(__('Access denied'), 'error');
  344. }
  345. return ($result);
  346. }
  347. /**
  348. * Delete aliase for number on Ubstorage
  349. *
  350. * @return void
  351. */
  352. public function AsteriskDeleteAlias($deleteAliasNum) {
  353. $newStoreAliases = $this->NumAliases;
  354. $deleteAliasNum = mysql_real_escape_string($deleteAliasNum);
  355. if (isset($newStoreAliases[$deleteAliasNum])) {
  356. unset($newStoreAliases[$deleteAliasNum]);
  357. $newStoreAliases = serialize($newStoreAliases);
  358. $newStoreAliases = base64_encode($newStoreAliases);
  359. zb_StorageSet('ASTERISK_NUMALIAS', $newStoreAliases);
  360. log_register("ASTERISK ALIAS DELETE `" . $deleteAliasNum . "`");
  361. rcms_redirect(self::URL_ME . '&config=true');
  362. }
  363. }
  364. /**
  365. * Create aliases for number on Ubstorage
  366. *
  367. * @return void
  368. */
  369. public function AsteriskCreateAlias($newAliasNum, $newAliasName) {
  370. $newStoreAliases = $this->NumAliases;
  371. $newAliasNum = mysql_real_escape_string($newAliasNum);
  372. $newAliasName = mysql_real_escape_string($newAliasName);
  373. $newStoreAliases[$newAliasNum] = $newAliasName;
  374. $newStoreAliases = serialize($newStoreAliases);
  375. $newStoreAliases = base64_encode($newStoreAliases);
  376. zb_StorageSet('ASTERISK_NUMALIAS', $newStoreAliases);
  377. log_register("ASTERISK ALIAS ADD `" . $newAliasNum . "` NAME `" . $newAliasName . "`");
  378. rcms_redirect(self::URL_ME . '&config=true');
  379. }
  380. /**
  381. * Update parametrs for Asterisk configs on Ubstorage
  382. *
  383. * @return void
  384. */
  385. public function AsteriskUpdateConfig($newhost, $newdb, $newtable, $newlogin, $newpassword, $newcachetime = '2592000', $dopmobile = '') {
  386. zb_StorageSet('ASTERISK_HOST', $newhost);
  387. zb_StorageSet('ASTERISK_DB', $newdb);
  388. zb_StorageSet('ASTERISK_TABLE', $newtable);
  389. zb_StorageSet('ASTERISK_LOGIN', $newlogin);
  390. zb_StorageSet('ASTERISK_PASSWORD', $newpassword);
  391. zb_StorageSet('ASTERISK_CACHETIME', ($newcachetime < 2592000) ? $newcachetime : 2592000);
  392. zb_StorageSet('ASTERISK_DOPMOBILE', $dopmobile);
  393. log_register('ASTERISK settings changed');
  394. rcms_redirect(self::URL_ME . '&config=true');
  395. }
  396. /**
  397. * Returns CDR date selection form
  398. *
  399. * @return string
  400. */
  401. public function panel() {
  402. global $user_login;
  403. $inputs = '';
  404. if (isset($user_login)) {
  405. $inputs .= wf_BackLink(self::URL_ME, '', false);
  406. }
  407. if (cfr('ASTERISKCONF')) {
  408. $inputs .= wf_Link(self::URL_ME . '&config=true', wf_img('skins/icon_extended.png') . ' ' . __('Settings'), false, 'ubButton') . ' ';
  409. }
  410. $inputs .= wf_DatePickerPreset('datefrom', curdate()) . ' ' . __('From');
  411. $inputs .= wf_DatePickerPreset('dateto', curdate()) . ' ' . __('To');
  412. if (!isset($user_login)) {
  413. $inputs .= wf_Trigger('countnum', __('Show the most annoying'), false);
  414. }
  415. $inputs .= wf_Submit(__('Show'));
  416. $result = wf_Form("", "POST", $inputs, 'glamour');
  417. if (!$this->connected) {
  418. $result .= $this->messages->getStyledMessage(__('Connection error for Asterisk Database'), 'error') . wf_tag('br/', false);
  419. }
  420. return ($result);
  421. }
  422. /**
  423. * Get comment for user
  424. *
  425. * @param int $idComments - comment id
  426. *
  427. * @return string
  428. */
  429. protected function AsteriskGetCommentsForUser($idComments) {
  430. $query = "SELECT `text` from `adcomments` WHERE `scope`='ASTERISK' AND `item`='" . $idComments . "' ORDER BY `date` ASC LIMIT 1;";
  431. $result = simple_query($query);
  432. $comments = $result["text"];
  433. return ($comments);
  434. }
  435. /**
  436. * Get status switch for user
  437. *
  438. * @param int $login - user login
  439. *
  440. * @return string
  441. */
  442. protected function AsteriskGetSWStatus($login) {
  443. $alldeadswitches = zb_SwitchesGetAllDead();
  444. $query = "SELECT `login`,`ip` FROM `switchportassign` LEFT JOIN `switches` ON switchportassign.switchid=switches.id WHERE `login`='" . $login . "';";
  445. $result_q = simple_query($query);
  446. if (empty($result_q)) {
  447. $result = 'ERROR: USER NOT HAVE SWITCH';
  448. } else {
  449. $result = isset($alldeadswitches[$result_q['ip']]) ? "DIE" : "OK";
  450. }
  451. return ($result);
  452. }
  453. /**
  454. * Get status switch and other for user, if his bumber have database. Use only in remote API.
  455. *
  456. * @param int $number, $param
  457. *
  458. * @return mixed
  459. */
  460. public function AsteriskGetInfoApi($number, $param) {
  461. $this->AsteriskGetLoginByNumberQuery();
  462. $number_cut = substr($number, -10);
  463. $login = @$this->result_NumberLogin[$number_cut];
  464. if (!empty($login)) {
  465. if ($param == "login") {
  466. $result = $login;
  467. } elseif ($param == "loginuniq") {
  468. $result = isset($this->result_NumberLoginUniq[$number_cut]) ? $this->result_NumberLoginUniq[$number_cut] : 'ERROR: USER HAVE MANY LOGINS';
  469. } elseif ($param == "swstatus") {
  470. $result = $this->AsteriskGetSWStatus($login);
  471. } elseif ($param == "realname") {
  472. $this->AsteriskGetUserAllRealnames();
  473. $realname = @$this->allrealnames[$login];
  474. $realname = preg_replace('/[^a-zA-Zа-яА-Я0-9ё\d ]+/iu', '', $realname);
  475. $realname = zb_TranslitString($realname, TRUE);
  476. $result = $login . "-" . $realname;
  477. } else {
  478. $result = 'ERROR: MISTAKE PARAMETR';
  479. }
  480. } else {
  481. $result = 'ERROR: NOT OUR USER';
  482. }
  483. return ($result);
  484. }
  485. /**
  486. * Converts per second time values to human-readable format
  487. *
  488. * @param int $seconds - time interval in seconds
  489. *
  490. * @return string
  491. */
  492. protected function AsteriskFormatTime($seconds) {
  493. $init = $seconds;
  494. $hours = floor($seconds / 3600);
  495. $minutes = floor(($seconds / 60) % 60);
  496. $seconds = $seconds % 60;
  497. if ($init < 3600) {
  498. //less than 1 hour
  499. if ($init < 60) {
  500. //less than minute
  501. $result = $seconds . ' ' . __('sec.');
  502. } else {
  503. //more than one minute
  504. $result = $minutes . ' ' . __('minutes') . ' ' . $seconds . ' ' . __('seconds');
  505. }
  506. } else {
  507. //more than hour
  508. $result = $hours . ' ' . __('hour') . ' ' . $minutes . ' ' . __('minutes') . ' ' . $seconds . ' ' . __('seconds');
  509. }
  510. return ($result);
  511. }
  512. /**
  513. * Gets Login by caller number from DB
  514. *
  515. * @return void
  516. */
  517. protected function AsteriskGetLoginByNumberQuery() {
  518. if (!isset($this->result_LoginByNumber) and empty($this->result_LoginByNumber)) {
  519. $result = array();
  520. $result_a = array();
  521. $resultUniq = array();
  522. $resultTempUniq = array();
  523. $resultNotUniq = array(); // It's need for future
  524. $queryPhone = "SELECT `phones`.`login`,`phone`,`mobile` FROM `phones`";
  525. $resultPhone = simple_queryall($queryPhone);
  526. foreach ($resultPhone as $data) {
  527. $result[$data['login']]['phone'] = substr($data['phone'], -10);
  528. $result_a[substr($data['phone'], -10)] = $data['login'];
  529. $result[$data['login']]['mobile'] = substr($data['mobile'], -10);
  530. $result_a[substr($data['mobile'], -10)] = $data['login'];
  531. if (!empty($result[$data['login']]['phone'])) {
  532. $resultTempUniq[substr($data['phone'], -10)][] = $data['login'];
  533. }
  534. if (!empty($result[$data['login']]['mobile'])) {
  535. $resultTempUniq[substr($data['mobile'], -10)][] = $data['login'];
  536. }
  537. }
  538. if ($this->config['dopmobile']) {
  539. $query_mobile_dop = "SELECT `login`,`content` FROM `cfitems` WHERE `typeid`='" . $this->config['dopmobile'] . "'";
  540. $result_md = simple_queryall($query_mobile_dop);
  541. foreach ($result_md as $data) {
  542. $result[$data['login']]['dop_mob'] = substr($data['content'], -10);
  543. $result_a[substr($data['content'], -10)] = $data['login'];
  544. $resultTempUniq[substr($data['content'], -10)][] = $data['login'];
  545. }
  546. }
  547. if ($this->altCfg['MOBILES_EXT']) {
  548. $query_mobileext = "SELECT `login`,`mobile` as `mobileext` FROM `mobileext`";
  549. $result_me = simple_queryall($query_mobileext);
  550. foreach ($result_me as $data) {
  551. $result[$data['login']]['mobileext'][] = substr($data['mobileext'], -10);
  552. $result_a[substr($data['mobileext'], -10)] = $data['login'];
  553. if (!empty($result[$data['login']]['mobileext'])) {
  554. $resultTempUniq[substr($data['mobileext'], -10)][] = $data['login'];
  555. }
  556. }
  557. }
  558. }
  559. // Try remove duplicate phone and mobile from one users
  560. foreach ($resultTempUniq as $phone => $dataArr) {
  561. $rawArr = array_unique($dataArr);
  562. if (count($rawArr) == 1) {
  563. $resultUniq[$phone] = $rawArr[0];
  564. } else {
  565. $resultNotUniq[$phone] = $rawArr;
  566. }
  567. }
  568. /*
  569. print "<pre>";
  570. print_r ($resultUniq);
  571. print "</pre>";
  572. */
  573. $this->result_LoginByNumber = $result;
  574. $this->result_NumberLogin = $result_a;
  575. $this->result_NumberLoginUniq = $resultUniq;
  576. }
  577. /**
  578. * Returns all of users realnames records as login=>realname array
  579. *
  580. * @return void
  581. */
  582. protected function AsteriskGetUserAllRealnames() {
  583. $this->allrealnames = zb_UserGetAllRealnames();
  584. }
  585. /**
  586. * Returns user address by some user login
  587. *
  588. * @return void
  589. */
  590. protected function AsteriskGetFulladdress() {
  591. $this->alladdress = zb_AddressGetFulladdresslistCached();
  592. }
  593. /**
  594. * Returns human readable alias from phone book by phone number
  595. *
  596. * @param string $number - phone number
  597. *
  598. * @return string
  599. */
  600. protected function AsteriskGetNumAlias($number) {
  601. if (!empty($this->NumAliases)) {
  602. if (isset($this->NumAliases[$number])) {
  603. return($number . ' - ' . $this->NumAliases[$number]);
  604. } else {
  605. return ($number);
  606. }
  607. } else {
  608. return ($number);
  609. }
  610. }
  611. /**
  612. * Gets Ubilling user login by number mobile
  613. *
  614. * @param string $number - number
  615. *
  616. * @return array
  617. */
  618. protected function AsteriskGetLoginByNumber($number) {
  619. if (strlen($number) == 13 or strlen(substr($number, -10)) == 10) {
  620. $number_cut = substr($number, -10);
  621. $user_by_number = @$this->result_NumberLogin[$number_cut];
  622. $result = array();
  623. if (!empty($user_by_number)) {
  624. $result['link'] = wf_Link('?module=userprofile&username=' . $user_by_number, $number, false);
  625. $result['login'] = $user_by_number;
  626. $result['name'] = @$this->allrealnames[$user_by_number];
  627. $result['adres'] = @$this->alladdress[$user_by_number];
  628. return ($result);
  629. } else {
  630. $result['link'] = $number;
  631. $result['login'] = '';
  632. $result['name'] = '';
  633. $result['adres'] = '';
  634. return ($result);
  635. }
  636. } else {
  637. $result['link'] = $this->AsteriskGetNumAlias($number);
  638. $result['login'] = '';
  639. $result['name'] = '';
  640. $result['adres'] = '';
  641. return ($result);
  642. }
  643. }
  644. /**
  645. * Gets Asterisk CDR data from database and manage cache
  646. * Load AsteriskGetLoginByNumberQuery, AsteriskGetUserAllRealnames, AsteriskGetFulladdress
  647. *
  648. * @return mixed
  649. */
  650. protected function AsteriskGetCDR() {
  651. $result = '';
  652. // Load needed function
  653. $this->AsteriskGetLoginByNumberQuery();
  654. $this->AsteriskGetUserAllRealnames();
  655. $this->AsteriskGetFulladdress();
  656. $from = isset($_GET['datefrom']) ? mysql_real_escape_string($_GET['datefrom']) : '2000-01-01';
  657. $to = isset($_GET['dateto']) ? mysql_real_escape_string($_GET['dateto']) : curdate();
  658. $asteriskTable = mysql_real_escape_string($this->config['table']);
  659. $user_login = isset($_GET['username']) ? vf($_GET['username']) : '';
  660. if (!empty($this->recordingsPath) and ! empty($this->recordingsCELTab)) {
  661. $cel = $this->recordingsCELTab;
  662. $query_flds = $asteriskTable . ".*, " . $cel . ".id, " . $cel . ".appname, SUBSTRING_INDEX(" . $cel . ".appdata, ',', 1) AS app_data ";
  663. $query_voice_join = " LEFT JOIN " . $cel . " ON " . $asteriskTable . ".calldate = " . $cel . ".eventtime " .
  664. " AND " . $asteriskTable . ".cnum = " . $cel . ".cid_num " .
  665. " AND (lower(" . $cel . ".appname) = 'monitor' OR lower(" . $cel . ".appname) = 'mixmonitor') ";
  666. } else {
  667. $query_flds = ' * ';
  668. $query_voice_join = '';
  669. }
  670. if (!empty($user_login)) {
  671. //fetch some data from Asterisk database
  672. $phone = @$this->result_LoginByNumber[$user_login]['phone'];
  673. $mobile = @$this->result_LoginByNumber[$user_login]['mobile'];
  674. $mobileext_arr = @$this->result_LoginByNumber[$user_login]['mobileext'];
  675. $dop_mobile = @$this->result_LoginByNumber[$user_login]['dop_mob'];
  676. // Building a query to the database
  677. $where_part = '';
  678. $query = "select " . $query_flds . " from `" . $asteriskTable . "` " . $query_voice_join . " where `calldate` BETWEEN '" . $from . " 00:00:00' AND '" . $to . " 23:59:59' AND (";
  679. if (!empty($phone) AND empty($where_part)) {
  680. $where_part .= "`src` LIKE '%" . $phone . "' OR `dst` LIKE '%" . $phone . "'";
  681. } elseif (!empty($phone) AND ! empty($where_part)) {
  682. $where_part .= " OR `src` LIKE '%" . $phone . "' OR `dst` LIKE '%" . $phone . "'";
  683. }
  684. if (!empty($mobile) AND empty($where_part)) {
  685. $where_part .= "`src` LIKE '%" . $mobile . "' OR `dst` LIKE '%" . $mobile . "'";
  686. } elseif (!empty($mobile) AND ! empty($where_part)) {
  687. $where_part .= " OR `src` LIKE '%" . $mobile . "' OR `dst` LIKE '%" . $mobile . "'";
  688. }
  689. if (!empty($mobileext_arr) AND empty($where_part)) {
  690. foreach ($mobileext_arr as $id => $mobileext) {
  691. if ($id == 0) {
  692. $where_part .= "`src` LIKE '%" . $mobileext . "' OR `dst` LIKE '%" . $mobileext . "'";
  693. } else {
  694. $where_part .= " OR `src` LIKE '%" . $mobileext . "' OR `dst` LIKE '%" . $mobileext . "'";
  695. }
  696. }
  697. } elseif (!empty($mobileext_arr) AND ! empty($where_part)) {
  698. foreach ($mobileext_arr as $mobileext) {
  699. $where_part .= " OR `src` LIKE '%" . $mobileext . "' OR `dst` LIKE '%" . $mobileext . "'";
  700. }
  701. }
  702. if (!empty($dop_mobile) AND empty($where_part)) {
  703. $where_part .= "`src` LIKE '%" . $dop_mobile . "' OR `dst` LIKE '%" . $dop_mobile . "'";
  704. } elseif (!empty($dop_mobile) AND ! empty($where_part)) {
  705. $where_part .= " OR `src` LIKE '%" . $dop_mobile . "' OR `dst` LIKE '%" . $dop_mobile . "'";
  706. }
  707. $query .= $where_part;
  708. $query .= ") AND (`lastapp`='dial' OR `lastapp`='queue') ORDER BY `calldate` DESC";
  709. if (!empty($where_part)) {
  710. $rawResult = $this->AsteriskQuery($query);
  711. }
  712. } elseif (wf_CheckGet(array('countnum')) and empty($user_login)) {
  713. $query = "select *,count(`src`) as `countnum` from `" . $asteriskTable . "` where `calldate` BETWEEN '" . $from . " 00:00:00' AND '" . $to . " 23:59:59' AND (`lastapp`='dial' OR `lastapp`='queue') GROUP BY `src`";
  714. $rawResult = $this->AsteriskQuery($query);
  715. } else {
  716. // check if need clean cache
  717. $this->AsterikCacheInfoClean($asteriskTable, $from, $to);
  718. // Start check cache and get result
  719. $query = "select " . $query_flds . " from `" . $asteriskTable . "` " . $query_voice_join . " where `calldate` BETWEEN '" . $from . " 00:00:00' AND '" . $to . " 23:59:59' AND (`lastapp`='dial' OR `lastapp`='queue') ORDER BY `calldate` DESC";
  720. $obj = $this;
  721. $cacheName = $from . $to;
  722. $rawResult = $this->cache->getCallback('ASTERISK_CDR_' . $cacheName, function() use ($query, $obj) {
  723. return ($obj->AsteriskQuery($query));
  724. }, $this->cacheTime);
  725. }
  726. // Check for rawResult
  727. if (!empty($rawResult)) {
  728. //here is data parsing
  729. $result = $rawResult;
  730. }
  731. return $result;
  732. }
  733. /**
  734. * Returns container of Asterisk
  735. *
  736. * @return string
  737. */
  738. public function renderAsteriskCDR() {
  739. $result = '';
  740. if (empty($this->recordingsPath)) {
  741. $columns = array('#', 'ID', 'Time', 'From', 'Real Name', 'Address', 'To', 'Type', 'Status', 'Talk time');
  742. } else {
  743. $columns = array('#', 'ID', 'Time', 'From', 'Real Name', 'Address', 'To', 'Type', 'Status', 'Talk time', 'Call recording');
  744. }
  745. if (wf_CheckPost(array('countnum')) and ! isset($user_login) and $_POST['countnum']) {
  746. $columns[] = __('Annoyance');
  747. $countnum = '&countnum=true';
  748. } else {
  749. $columns[] = 'Comments';
  750. $countnum = '';
  751. }
  752. $from = isset($_POST['datefrom']) ? $_POST['datefrom'] : '2000-01-01';
  753. $to = isset($_POST['dateto']) ? $_POST['dateto'] : curdate();
  754. $user_login = isset($_GET['username']) ? '&username=' . vf($_GET['username']) : '';
  755. $opts = '"order": [[ 0, "asc" ]]';
  756. $result = wf_JqDtLoader($columns, '?module=asterisk&ajax=true&datefrom=' . $from . '&dateto=' . $to . $user_login . $countnum, false, 'Calls', 100, $opts);
  757. return ($result);
  758. }
  759. /**
  760. * Parse Asterisk RAW CDR data
  761. *
  762. * @return void
  763. */
  764. public function ajaxAvaibleCDR() {
  765. $cdrData = $this->AsteriskGetCDR();
  766. $adcomments = new ADcomments('ASTERISK'); // minus one SQL query per call
  767. $json = new wf_JqDtHelper();
  768. if (!empty($cdrData)) {
  769. $totalTime = 0;
  770. $callsCounter = 0;
  771. $allVoiceFiles = (empty($this->recordingsPath)) ? array() : $this->getCallsRecords();
  772. foreach ($cdrData as $io => $each) {
  773. if (!$this->getFullCDRCELData and isset($cdrData[$io - 1]['src'])) {
  774. if ($cdrData[$io]['src'] == $cdrData[$io - 1]['src'] and $cdrData[$io - 1]['disposition'] == 'NO ANSWER' and $cdrData[$io]['disposition'] != 'ANSWERED')
  775. continue;
  776. if ($cdrData[$io]['src'] == $cdrData[$io - 1]['src'] and $cdrData[$io - 1]['dst'] == 'hangup')
  777. continue;
  778. if ($cdrData[$io]['src'] == $cdrData[$io - 1]['src'] and $cdrData[$io - 1]['dst'] == 'musiconhold')
  779. continue;
  780. }
  781. $callsCounter++;
  782. $AsteriskGetLoginByNumberAraySrc = array($this->AsteriskGetLoginByNumber($each['src']));
  783. foreach ($AsteriskGetLoginByNumberAraySrc as $tempDataSrc) {
  784. $link_src = $tempDataSrc['link'];
  785. $login = $tempDataSrc['login'];
  786. $name_src = $tempDataSrc['name'];
  787. $adres_src = $tempDataSrc['adres'];
  788. }
  789. $AsteriskGetLoginByNumberArayDst = array($this->AsteriskGetLoginByNumber($each['dst']));
  790. foreach ($AsteriskGetLoginByNumberArayDst as $tempDataDst) {
  791. $link_dst = $tempDataDst['link'];
  792. if (!empty($tempDataDst['login'])) {
  793. $login = $tempDataDst['login'];
  794. }
  795. }
  796. $debugData = wf_tag('pre') . print_r($each, true) . wf_tag('pre', true);
  797. $startTime = $each['calldate'];
  798. $tmpTime = strtotime($each['calldate']);
  799. $endTime = $tmpTime + $each['duration'];
  800. $endTime = date("H:i:s", $endTime);
  801. $answerTime = $tmpTime + ($each['duration'] - $each['billsec']);
  802. $answerTime = date("H:i:s", $answerTime);
  803. $tmpStats = __('Taken up the phone') . ': ' . $answerTime . "\n";
  804. $tmpStats .= __('End of call') . ': ' . $endTime;
  805. $sessionTimeStats = wf_tag('abbr', false, '', 'title="' . $tmpStats . '"');
  806. $sessionTimeStats .= $startTime;
  807. $sessionTimeStats .= wf_tag('abbr', true);
  808. $callDirection = '';
  809. $CallType = __('Dial');
  810. if (ispos($each['lastapp'], 'internal-caller-transfer')) {
  811. $CallType = __('Call transfer');
  812. }
  813. $callStatus = $each['disposition'];
  814. $statusIcon = '';
  815. if (ispos($each['disposition'], 'ANSWERED')) {
  816. $callStatus = __('Answered');
  817. $statusIcon = wf_img('skins/calls/phone_green.png');
  818. }
  819. if (ispos($each['disposition'], 'NO ANSWER')) {
  820. $callStatus = __('No answer');
  821. $statusIcon = wf_img('skins/calls/phone_red.png');
  822. }
  823. if (ispos($each['disposition'], 'BUSY')) {
  824. $callStatus = __('Busy');
  825. $statusIcon = wf_img('skins/calls/phone_yellow.png');
  826. }
  827. if (ispos($each['disposition'], 'FAILED')) {
  828. $callStatus = __('Failed');
  829. $statusIcon = wf_img('skins/calls/phone_fail.png');
  830. }
  831. $speekTime = $each['billsec'];
  832. $totalTime = $totalTime + $each['billsec'];
  833. $speekTime = $this->AsteriskFormatTime($speekTime);
  834. $data[] = $callsCounter;
  835. $data[] = wf_modal($callsCounter, $callsCounter, $debugData, '', '500', '600');
  836. $data[] = $sessionTimeStats;
  837. $data[] = $link_src;
  838. $data[] = $name_src;
  839. $data[] = $adres_src;
  840. $data[] = $link_dst;
  841. $data[] = $CallType;
  842. $data[] = $statusIcon . ' ' . $callStatus;
  843. $data[] = $speekTime;
  844. if (!empty($this->recordingsPath)) {
  845. if (isset($each['app_data']) and array_key_exists($each['app_data'], $allVoiceFiles)) {
  846. $callrecPath = $allVoiceFiles[$each['app_data']] . $each['app_data'];
  847. $fileUrl = self::URL_ME . '&astercallrecs=' . urlencode($callrecPath);
  848. $data[] = $this->getSoundcontrolsHTML5($fileUrl, $callrecPath);
  849. } elseif (isset($each['recordingfile']) and array_key_exists($each['recordingfile'], $allVoiceFiles)) {
  850. $callrecPath = $allVoiceFiles[$each['recordingfile']] . $each['recordingfile'];
  851. $fileUrl = self::URL_ME . '&astercallrecs=' . urlencode($callrecPath);
  852. $data[] = $this->getSoundcontrolsHTML5($fileUrl, $callrecPath);
  853. } elseif (isset($each['filename']) and array_key_exists($each['filename'], $allVoiceFiles)) {
  854. $callrecPath = $allVoiceFiles[$each['filename']] . $each['filename'];
  855. // То, что в each - это название столбца, в моём случае у меня всё было в filename
  856. $fileUrl = self::URL_ME . '&astercallrecs=' . urlencode($callrecPath);
  857. $data[] = $this->getSoundcontrolsHTML5($fileUrl, $callrecPath);
  858. } else {
  859. $data[] = '';
  860. }
  861. }
  862. if (wf_CheckGet(array('countnum')) and ! isset($user_login) and $_GET['countnum']) {
  863. $data[] = $each['countnum'];
  864. } else {
  865. $itemId = $each['uniqueid'] . $each['disposition'][0];
  866. if ($adcomments->haveComments($itemId)) {
  867. $link_text = wf_tag('center') . $adcomments->getCommentsIndicator($itemId) . wf_tag('br') . wf_tag('span', false, '', 'style="font-size:14px;color: black;"') . $this->AsteriskGetCommentsForUser($itemId) . wf_tag('span', true) . wf_tag('center', true);
  868. } else {
  869. $link_text = wf_tag('center') . __('Add comments') . wf_tag('center', true);
  870. }
  871. if (!empty($login)) {
  872. $data[] = wf_Link(self::URL_ME . '&addComments=' . $itemId . '&username=' . $login . '#profileending', $link_text, false);
  873. } else {
  874. $data[] = wf_Link(self::URL_ME . '&addComments=' . $itemId . '&AsteriskWindow=1', $link_text, false);
  875. }
  876. }
  877. $json->addRow($data);
  878. unset($data);
  879. }
  880. }
  881. $json->getJson();
  882. }
  883. /**
  884. * Inits gsm/wav player for further usage
  885. * @DEPRECATED
  886. *
  887. * @return string
  888. */
  889. public function initPlayer() {
  890. $result = '';
  891. $result .= wf_tag('script', false, '', 'src="modules/jsc/wavplay/embed/domready.js"') . wf_tag('script', true);
  892. $result .= wf_tag('script', false, '', 'src="modules/jsc/wavplay/embed/swfobject.js"') . wf_tag('script', true);
  893. $result .= wf_tag('script', false, '', 'src="modules/jsc/wavplay/embed/tinywav.js"') . wf_tag('script', true);
  894. return ($result);
  895. }
  896. /**
  897. * Returns controls for some recorded call file
  898. * @DEPRECATED
  899. *
  900. * @param string $fileUrl
  901. *
  902. * @return string
  903. */
  904. public function getSoundControls($fileUrl) {
  905. $result = '';
  906. if (!empty($fileUrl)) {
  907. $result .= wf_tag('a', false, '', 'onclick="try{window.TinyWav.Play(\'' . $fileUrl . '\')}catch(E){alert(E)}"') . wf_img('skins/play.png', __('Play')) . wf_tag('a', true) . ' ';
  908. $result .= wf_tag('a', false, '', 'onclick="try{window.TinyWav.Pause()}catch(E){alert(E)}"') . wf_img('skins/pause.png', __('Pause')) . wf_tag('a', true) . ' ';
  909. $result .= wf_tag('a', false, '', 'onclick="try{window.TinyWav.Resume()}catch(E){alert(E)}"') . wf_img('skins/continue.png', __('Continue')) . wf_tag('a', true) . ' ';
  910. $result .= wf_Link($fileUrl, wf_img('skins/icon_download.png', __('Download')));
  911. }
  912. return ($result);
  913. }
  914. protected function getSoundcontrolsHTML5($fileUrl, $filename) {
  915. $result = '';
  916. if (!empty($fileUrl)) {
  917. $playableUrl = $fileUrl . '&playable=true';
  918. $playerId = 'player_' . wf_InputId();
  919. if ($filename != "" && file_exists($filename)) {
  920. $result.= wf_tag('audio', false, '', 'controls id="' . $playerId . '" src="' . $playableUrl . '" preload="none" style="width: 300px;"');
  921. $result.= wf_tag('audio', true);
  922. }
  923. }
  924. return ($result);
  925. }
  926. /**
  927. * Catches file download
  928. *
  929. * @return void
  930. */
  931. public function catchFileDownload() {
  932. if (wf_CheckGet(array('astercallrecs'))) {
  933. zb_DownloadFile(ubRouting::get('astercallrecs'), 'default');
  934. }
  935. }
  936. /**
  937. * Returns available calls files array
  938. *
  939. * @return array
  940. */
  941. protected function getCallsRecords() {
  942. $result = array();
  943. $exp = '/^' . str_replace('*', '(.*)', str_replace('.', '\\.', $this->recordingsFormat)) . '$/';
  944. $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->recordingsPath));
  945. foreach ($rii as $file) {
  946. if (!$file->isDir()) {
  947. if (!empty($this->recordingsFormat) and preg_match($exp, $file->getPathname())) {
  948. $dirPath = rtrim($file->getPath(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
  949. $result[$file->getFilename()] = $dirPath;
  950. } else {
  951. $dirPath = rtrim($file->getPath(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
  952. $result[$file->getFilename()] = $dirPath;
  953. }
  954. }
  955. }
  956. return ($result);
  957. }
  958. /**
  959. * Returns all logins for a given phone number or a part of phone number
  960. *
  961. * @param $mobile
  962. * @param bool $returnJSON
  963. *
  964. * @return array|string
  965. */
  966. public function getLoginsByMobile($mobile, $returnJSON = true) {
  967. $logins = array();
  968. $query = "(SELECT `login` FROM `phones` WHERE `mobile` LIKE '%" . $mobile . "%')
  969. UNION ALL
  970. (SELECT `login` FROM `mobileext` WHERE `mobile` LIKE '%" . $mobile . "%')";
  971. $queryResult = simple_queryall($query);
  972. if (!empty($queryResult)) {
  973. foreach ($queryResult as $eachRec) {
  974. $logins[] = $eachRec['login'];
  975. }
  976. }
  977. $logins = ($returnJSON) ? json_encode($logins) : $logins;
  978. return ($logins);
  979. }
  980. /**
  981. * Returns all contracts for a given phone number or a part of phone number
  982. *
  983. * @param $mobile
  984. * @param bool $returnJSON
  985. *
  986. * @return array|string
  987. */
  988. public function getContractsByMobile($mobile, $returnJSON = true) {
  989. $contracts = array();
  990. $logins = $this->getLoginsByMobile($mobile, false);
  991. if (!empty($logins)) {
  992. foreach ($logins as $eachLogin) {
  993. $contracts[] = zb_UserGetContract($eachLogin);
  994. }
  995. }
  996. $contracts = ($returnJSON) ? json_encode($contracts) : $contracts;
  997. return ($contracts);
  998. }
  999. /**
  1000. * Returns some user data by login with optional auth by login + password
  1001. *
  1002. * @param $login
  1003. * @param string $passwd
  1004. * @param bool $getExtMobiles
  1005. * @param bool $returnJSON
  1006. *
  1007. * @return array|string
  1008. */
  1009. public function getUserData($login, $passwd = '', $getExtMobiles = true, $returnJSON = true) {
  1010. $userData = array();
  1011. if (!is_array($login) and ! empty($passwd)) {
  1012. $allUsers = zb_UserGetAllDataCache();
  1013. if (empty($allUsers[$login]) or $allUsers[$login]['Password'] !== $passwd) {
  1014. $userData['ERROR'] = 'Auth failed';
  1015. $userData = ($returnJSON) ? json_encode($userData) : $userData;
  1016. return ($userData);
  1017. }
  1018. }
  1019. if (is_array($login)) {
  1020. $login = "'" . implode("','", $login) . "'";
  1021. $whereStr = "WHERE `users`.`login` IN (" . $login . ")";
  1022. } else {
  1023. $whereStr = "WHERE `users`.`login` = '" . $login . "'";
  1024. }
  1025. $query = "SELECT `login`, `Password`, `Cash`, `Credit`, `CreditExpire`, `Passive`, `Down`, `AlwaysOnline`, `Tariff`,
  1026. `tariffs`.`Fee`, `tariffs`.`period`, `contracts`.`contract`, `phones`.`mobile`, `tAgents`.`agentid`, `tAgents`.`contrname`
  1027. FROM `users`
  1028. LEFT JOIN `tariffs` ON (`users`.`Tariff` = `tariffs`.`name`)
  1029. LEFT JOIN `contracts` USING(`login`)
  1030. LEFT JOIN `phones` USING(`login`)
  1031. LEFT JOIN (SELECT `agentid`, `login`, `contrahens`.`contrname` FROM `ahenassignstrict`
  1032. LEFT JOIN `contrahens` ON `ahenassignstrict`.`agentid` = `contrahens`.`id`) AS `tAgents` USING(`login`)
  1033. " . $whereStr;
  1034. $queryResult = simple_queryall($query);
  1035. if (!empty($queryResult)) {
  1036. foreach ($queryResult as $eachRec) {
  1037. $tmpLogin = $eachRec['login'];
  1038. if ($this->extMobilesON and $getExtMobiles) {
  1039. $extMob = new MobilesExt();
  1040. $allExtMobs = $extMob->getUserMobiles($eachRec['login'], true);
  1041. $eachRec['ext_mobiles'] = (empty($allExtMobs[$tmpLogin])) ? array() : $allExtMobs[$tmpLogin];
  1042. }
  1043. $userData[$tmpLogin] = $eachRec;
  1044. }
  1045. }
  1046. $userData = ($returnJSON) ? json_encode($userData) : $userData;
  1047. return ($userData);
  1048. }
  1049. /**
  1050. * Adds or creates user mobiles with max mobiles count threshold support
  1051. *
  1052. * @param $login
  1053. * @param $mobile
  1054. * @param int $maxMobilesCnt
  1055. * @param bool $returnJSON
  1056. *
  1057. * @return array|string
  1058. */
  1059. public function addUserMobile($login, $mobile, $maxMobilesCnt = 0, $returnJSON = true) {
  1060. $allPhones = zb_GetAllAllPhonesCache();
  1061. $result = array();
  1062. if (!empty($allPhones[$login])) {
  1063. $curUserPhones = $allPhones[$login];
  1064. $noMainMobileSet = empty($curUserPhones['mobile']);
  1065. //check if such mobile already exists for this user
  1066. if ($curUserPhones['mobile'] == $mobile or in_array($mobile, $curUserPhones['mobiles'])) {
  1067. $result['ERROR'] = 'Such mobile already exists for this user';
  1068. $result = ($returnJSON) ? json_encode($result) : $result;
  1069. return ($result);
  1070. }
  1071. // check if user mobiles count reached $maxMobilesCnt
  1072. if (!empty($maxMobilesCnt)) {
  1073. $curMobsCnt = ($noMainMobileSet) ? 0 : 1;
  1074. $curMobsCnt += count($curUserPhones['mobiles']);
  1075. if ($curMobsCnt >= $maxMobilesCnt) {
  1076. $result['ERROR'] = 'Max mobiles count threshold reached';
  1077. $result = ($returnJSON) ? json_encode($result) : $result;
  1078. return ($result);
  1079. }
  1080. }
  1081. if ($noMainMobileSet) {
  1082. zb_UserChangeMobile($login, $mobile);
  1083. } else {
  1084. $extMob = new MobilesExt();
  1085. $extMob->createUserMobile($login, $mobile, 'Added by Asterisk');
  1086. }
  1087. } else {
  1088. zb_UserCreatePhone($login, '', $mobile);
  1089. }
  1090. $cache = new UbillingCache();
  1091. $cache->delete('USER_ALL_PHONES_DATA');
  1092. $result['SUCCES'] = 'Mobile added';
  1093. $result = ($returnJSON) ? json_encode($result) : $result;
  1094. return ($result);
  1095. }
  1096. }
  1097. ?>