api.stigma.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. <?php
  2. /**
  3. * This class allow cast abstract stigmatization of random objects placed in random scopes.
  4. */
  5. class Stigma {
  6. /**
  7. * Contains current instance stigma-scope
  8. *
  9. * @var string
  10. */
  11. protected $scope = '';
  12. /**
  13. * Contains current instance type: checklist or radiolist
  14. *
  15. * @var string
  16. */
  17. protected $type = 'radiolist';
  18. /**
  19. * Stigma controller renderer type: iconic, selector, textlink, etc...
  20. *
  21. * @var string
  22. */
  23. protected $renderer = 'iconic';
  24. /**
  25. * Contains available stigma type icons as state=>iconname
  26. *
  27. * @var array
  28. */
  29. protected $icons = array();
  30. /**
  31. * Contains all of states available in current scope as state=>name
  32. *
  33. * @var array
  34. */
  35. protected $states = array();
  36. /**
  37. * Contains current administrator login
  38. *
  39. * @var string
  40. */
  41. protected $myLogin = '';
  42. /**
  43. * Database abstraction layer placeholder
  44. *
  45. * @var object
  46. */
  47. protected $stigmaDb = '';
  48. /**
  49. * Contains all of available stigmas from database as itemid=>data
  50. *
  51. * @var array
  52. */
  53. protected $allStigmas = '';
  54. /**
  55. * Contains controller callbacks URL
  56. *
  57. * @var string
  58. */
  59. protected $baseUrl = '';
  60. /**
  61. * Configurable active-state class
  62. *
  63. * @var string
  64. */
  65. protected $activeClass = 'todaysig';
  66. /**
  67. * Configurable base-state controls class
  68. *
  69. * @var string
  70. */
  71. protected $baseClass = 'dashtask';
  72. /**
  73. * Stigma content update animation
  74. *
  75. * @var bool
  76. */
  77. protected $animated = true;
  78. /**
  79. * Taskman logging flag/parameter name. Disabled if empty.
  80. *
  81. * @var string
  82. */
  83. protected $taskmanLogging = '';
  84. /**
  85. * System weblogs logging flag/parameter name. Disabled if empty.
  86. *
  87. * @var string
  88. */
  89. protected $systemLogging = '';
  90. /**
  91. * System custom logging flag/table name. Disabled if empty.
  92. *
  93. * @var string
  94. */
  95. protected $customLogging = '';
  96. /**
  97. * Default icons file extension
  98. */
  99. const ICON_EXT = '.png';
  100. /**
  101. * Default state icons path
  102. */
  103. const ICON_PATH = 'skins/stigma/';
  104. /**
  105. * Default stigma configuration files path
  106. */
  107. const CONFIG_PATH = 'config/stigma/';
  108. /**
  109. * Custom stigma configs path. Have higher priority on loading.
  110. */
  111. const CUSTOM_CONFIG_PATH = 'content/documents/mystigma/confs/';
  112. /**
  113. * Custom stigma icons path. Search icons at start at CUSTOM_ICON_PATH then on ICON_PATH.
  114. */
  115. const CUSTOM_ICON_PATH = 'content/documents/mystigma/icons/';
  116. /**
  117. * per-scope configuration files extension
  118. */
  119. const CONFIG_EXT = '.ini';
  120. /**
  121. * Contains default datasource table name
  122. */
  123. const TABLE_DATASOURCE = 'stigma';
  124. /**
  125. * Contains defaul states delimiter for multiple states
  126. */
  127. const DELIMITER = '|';
  128. /**
  129. * Renderer methods names prefix
  130. */
  131. const RENDERER_PREFIX = 'renderer';
  132. /**
  133. * Some URLS/routes etc
  134. */
  135. const ROUTE_SCOPE = 'stscope';
  136. const ROUTE_ITEMID = 'stitemid';
  137. const ROUTE_STATE = 'stchstate';
  138. const ROUTE_ICONSIZE = 'stis';
  139. /**
  140. * Creates new stigma on selected scope
  141. *
  142. * @param string $scope scope string identifier of stigma instance
  143. * @param string $loadOnlyItem preload only some itemId data in selected scope
  144. */
  145. public function __construct($scope, $loadOnlyItem = '') {
  146. // ______
  147. // .d$$$******$$$$c.
  148. // .d$P" "$$c
  149. // $$$$$. .$$$*$.
  150. // .$$ 4$L*$$. .$$Pd$ '$b
  151. // $F *$. "$$e.e$$" 4$F ^$b
  152. // d$ $$ z$$$e $$ '$.
  153. // $P `$L$$P` `"$$d$" $$
  154. // $$ e$$F 4$$b. $$
  155. // $b .$$" $$ .$$ "4$b. $$
  156. // $$e$P" $b d$` "$$c$F
  157. // '$P$$$$$$$$$$$$$$$$$$$$$$$$$$
  158. // "$c. 4$. $$ .$$
  159. // ^$$. $$ d$" d$P
  160. // "$$c. `$b$F .d$P"
  161. // `4$$$c.$$$..e$$P"
  162. // `^^^^^^^`
  163. $this->setScope($scope);
  164. $this->setBaseUrl();
  165. $this->setAdminLogin();
  166. $this->initDatabase();
  167. $this->loadConfig();
  168. $this->loadStigmas($loadOnlyItem);
  169. }
  170. /**
  171. * Sets current instance scope
  172. *
  173. * @param string $scope
  174. * @throws Exception
  175. *
  176. * @return void
  177. */
  178. protected function setScope($scope) {
  179. if (!empty($scope)) {
  180. $this->scope = ubRouting::filters($scope, 'mres');
  181. } else {
  182. throw new Exception('EX_EMPTY_SCOPE');
  183. }
  184. }
  185. /**
  186. * Sets current instance base URL
  187. *
  188. * @throws Exception
  189. *
  190. * @return void
  191. */
  192. protected function setBaseUrl() {
  193. $url = '';
  194. $getVars = ubRouting::rawGet();
  195. $myRoutes = array(self::ROUTE_ICONSIZE, self::ROUTE_ITEMID, self::ROUTE_SCOPE, self::ROUTE_STATE);
  196. $myRoutes = array_flip($myRoutes);
  197. if (!empty($getVars)) {
  198. $url = '?';
  199. foreach ($getVars as $getVar => $getVal) {
  200. if (!isset($myRoutes[$getVar])) {
  201. $url .= $getVar . '=' . $getVal . '&';
  202. }
  203. }
  204. }
  205. if (!empty($url)) {
  206. $this->baseUrl = $url;
  207. } else {
  208. throw new Exception('EX_EMPTY_BASEURL');
  209. }
  210. }
  211. /**
  212. * Sets current administrator login property
  213. *
  214. * @return void
  215. */
  216. protected function setAdminLogin() {
  217. $this->myLogin = whoami();
  218. }
  219. /**
  220. * Creates protected database abstraction layer
  221. *
  222. * @return void
  223. */
  224. protected function initDatabase() {
  225. $this->stigmaDb = new NyanORM(self::TABLE_DATASOURCE);
  226. }
  227. /**
  228. * Taskman logging flag/name public setter
  229. *
  230. * @param string $parameter
  231. *
  232. * @return void
  233. */
  234. public function setTaskmanLogging($parameter = '') {
  235. $this->taskmanLogging = $parameter;
  236. }
  237. /**
  238. * System weblogs logging flag/name public setter
  239. *
  240. * @param string $parameter
  241. *
  242. * @return void
  243. */
  244. public function setSystemLogging($parameter = '') {
  245. $this->systemLogging = $parameter;
  246. }
  247. /**
  248. * System custom database table logging flag/name public setter
  249. *
  250. * @param string $parameter
  251. *
  252. * @return void
  253. */
  254. public function setCustomLogging($parameter = '') {
  255. $this->customLogging = $parameter;
  256. }
  257. /**
  258. * Preloads current scope settings from config file
  259. *
  260. * @throws Exception
  261. *
  262. * @return void
  263. */
  264. protected function loadConfig() {
  265. $confName = strtolower($this->scope);
  266. $confFullPath = self::CUSTOM_CONFIG_PATH . $confName . self::CONFIG_EXT;
  267. if (!file_exists($confFullPath)) {
  268. //use default path
  269. $confFullPath = self::CONFIG_PATH . $confName . self::CONFIG_EXT;
  270. }
  271. if (file_exists($confFullPath)) {
  272. $raw = rcms_parse_ini_file($confFullPath, true);
  273. /**
  274. * One nation, one clan
  275. * As the sun unites our hands
  276. * Each colour, each tribe
  277. * Where the eagle cries with pride
  278. */
  279. if (isset($raw['stigmasettings'])) {
  280. if (isset($raw['stigmasettings']['TYPE'])) {
  281. $this->type = $raw['stigmasettings']['TYPE'];
  282. if (isset($raw['stigmasettings']['ACTIVECLASS'])) {
  283. $this->activeClass = $raw['stigmasettings']['ACTIVECLASS'];
  284. }
  285. if (isset($raw['stigmasettings']['BASECLASS'])) {
  286. $this->baseClass = $raw['stigmasettings']['BASECLASS'];
  287. }
  288. if (isset($raw['stigmasettings']['ANIMATION'])) {
  289. $this->animated = ($raw['stigmasettings']['ANIMATION']) ? false : true;
  290. }
  291. if (isset($raw['stigmasettings']['RENDERER'])) {
  292. $this->renderer = $raw['stigmasettings']['RENDERER'];
  293. }
  294. foreach ($raw as $io => $each) {
  295. if ($io != 'stigmasettings') {
  296. $this->states[$io] = $each['NAME'];
  297. if (isset($each['ICON'])) {
  298. $this->icons[$io] = $each['ICON'];
  299. }
  300. }
  301. }
  302. } else {
  303. throw new Exception('EX_STIGMATYPE_MISSED');
  304. }
  305. } else {
  306. throw new Exception('EX_STIGMASETTINGS_SECTION_MISSED');
  307. }
  308. } else {
  309. throw new Exception('EX_CONF_NOT_EXISTS');
  310. }
  311. }
  312. /**
  313. * Loads all states from database for current scope
  314. *
  315. * @param string $loadOnlyItem preload only some itemId data in selected scope
  316. *
  317. * @return void
  318. */
  319. protected function loadStigmas($loadOnlyItem = '') {
  320. $this->stigmaDb->where('scope', '=', $this->scope);
  321. if (!empty($loadOnlyItem)) {
  322. $itemFilter = ubRouting::filters($loadOnlyItem, 'mres');
  323. $this->stigmaDb->where('itemid', '=', $itemFilter);
  324. }
  325. $this->allStigmas = $this->stigmaDb->getAll('itemid');
  326. }
  327. /**
  328. * Returns some stateId icon if available or default icon if not.
  329. *
  330. * @param string $stateId
  331. *
  332. * @return string
  333. */
  334. public function getStateIcon($stateId) {
  335. $result = '';
  336. if (file_exists(self::CUSTOM_ICON_PATH . @$this->icons[$stateId] . self::ICON_EXT)) {
  337. $result = self::CUSTOM_ICON_PATH . @$this->icons[$stateId] . self::ICON_EXT;
  338. } else {
  339. if (file_exists(self::ICON_PATH . @$this->icons[$stateId] . self::ICON_EXT)) {
  340. $result = self::ICON_PATH . @$this->icons[$stateId] . self::ICON_EXT;
  341. }
  342. }
  343. if (empty($result)) {
  344. $result = self::ICON_PATH . 'default' . self::ICON_EXT;
  345. }
  346. return($result);
  347. }
  348. /**
  349. * Returns default iconic renderer controls
  350. *
  351. * @param string $itemId
  352. * @param int $size
  353. * @param bool $readOnly
  354. * @param array $currentStates
  355. * @param string $containerName
  356. *
  357. * @return string
  358. */
  359. protected function rendererIconic($itemId, $size = '', $readOnly = false, $currentStates, $containerName) {
  360. $result = '';
  361. foreach ($this->states as $stateId => $stateName) {
  362. $stateLabel = __($stateName);
  363. $controlClass = $this->baseClass;
  364. if (isset($currentStates[$stateId])) {
  365. $controlClass .= ' ' . $this->activeClass;
  366. }
  367. $stateIcon = $this->getStateIcon($stateId);
  368. $controlUrl = $this->baseUrl . '&' . self::ROUTE_SCOPE . '=' . $this->scope . '&' . self::ROUTE_ITEMID . '=' . $itemId . '&' . self::ROUTE_STATE . '=' . $stateId;
  369. if ($size) {
  370. $controlUrl .= '&' . self::ROUTE_ICONSIZE . '=' . $size;
  371. }
  372. if (!$readOnly) {
  373. $controlLink = wf_AjaxLink($controlUrl, wf_img_sized($stateIcon, $stateLabel, $size), $containerName);
  374. } else {
  375. $controlLink = wf_img_sized($stateIcon, $stateLabel, $size);
  376. }
  377. $result .= wf_tag('div', false, $controlClass, '');
  378. $result .= $controlLink;
  379. $result .= wf_delimiter(0) . $stateLabel;
  380. $result .= wf_tag('div', true);
  381. }
  382. return($result);
  383. }
  384. /**
  385. * Returns selector renderer controls
  386. *
  387. * @param string $itemId
  388. * @param int $size
  389. * @param bool $readOnly
  390. * @param array $currentStates
  391. * @param string $containerName
  392. *
  393. * @return string
  394. */
  395. protected function rendererSelector($itemId, $size = '', $readOnly = false, $currentStates, $containerName) {
  396. $result = '';
  397. $params = array();
  398. $disabled = '';
  399. $selected = '';
  400. foreach ($this->states as $stateId => $stateName) {
  401. $controlUrl = $this->baseUrl . '&' . self::ROUTE_SCOPE . '=' . $this->scope . '&' . self::ROUTE_ITEMID . '=' . $itemId . '&' . self::ROUTE_STATE . '=' . $stateId;
  402. if (isset($currentStates[$stateId])) {
  403. $selected = $controlUrl;
  404. }
  405. if ($readOnly) {
  406. $disabled = ' DISABLED';
  407. }
  408. $stateLabel = __($stateName);
  409. $params[$controlUrl] = $stateLabel;
  410. }
  411. $result .= wf_AjaxSelectorAC($containerName, $params, '', $selected, false, $disabled);
  412. return($result);
  413. }
  414. /**
  415. * Returns text links renderer controls
  416. *
  417. * @param string $itemId
  418. * @param int $size
  419. * @param bool $readOnly
  420. * @param array $currentStates
  421. * @param string $containerName
  422. *
  423. * @return string
  424. */
  425. protected function rendererTextlink($itemId, $size = '', $readOnly = false, $currentStates, $containerName) {
  426. $result = '';
  427. foreach ($this->states as $stateId => $stateName) {
  428. $stateLabel = __($stateName);
  429. $controlClass = $this->baseClass;
  430. if (isset($currentStates[$stateId])) {
  431. $controlClass .= ' ' . $this->activeClass;
  432. }
  433. $controlUrl = $this->baseUrl . '&' . self::ROUTE_SCOPE . '=' . $this->scope . '&' . self::ROUTE_ITEMID . '=' . $itemId . '&' . self::ROUTE_STATE . '=' . $stateId;
  434. if (!$readOnly) {
  435. $controlLink = wf_AjaxLink($controlUrl, $stateLabel, $containerName, false, $controlClass);
  436. } else {
  437. $controlLink = wf_Link('#', $stateLabel, false, $controlClass);
  438. }
  439. $result .= $controlLink . ' ';
  440. }
  441. return($result);
  442. }
  443. /**
  444. * Returns text links and small images renderer controls
  445. *
  446. * @param string $itemId
  447. * @param int $size
  448. * @param bool $readOnly
  449. * @param array $currentStates
  450. * @param string $containerName
  451. *
  452. * @return string
  453. */
  454. protected function rendererImagelink($itemId, $size = '', $readOnly = false, $currentStates, $containerName) {
  455. $result = '';
  456. foreach ($this->states as $stateId => $stateName) {
  457. $stateLabel = __($stateName);
  458. $controlClass = $this->baseClass;
  459. if (isset($currentStates[$stateId])) {
  460. $controlClass .= ' ' . $this->activeClass;
  461. }
  462. $stateIcon = $this->getStateIcon($stateId);
  463. $controlUrl = $this->baseUrl . '&' . self::ROUTE_SCOPE . '=' . $this->scope . '&' . self::ROUTE_ITEMID . '=' . $itemId . '&' . self::ROUTE_STATE . '=' . $stateId;
  464. if (!$readOnly) {
  465. $controlLink = wf_AjaxLink($controlUrl, wf_img_sized($stateIcon, $stateLabel, 16) . ' ' . $stateLabel, $containerName, false, $controlClass);
  466. } else {
  467. $controlLink = wf_Link('#', wf_img_sized($stateIcon, $stateLabel, 16) . ' ' . $stateLabel, false, $controlClass);
  468. }
  469. $result .= $controlLink . ' ';
  470. }
  471. return($result);
  472. }
  473. /**
  474. * Renders stigma current state and editing interface for some item
  475. *
  476. * @param string $itemId item ID to render control panel
  477. * @param int $size optional size of state icons
  478. * @param bool $readOnly render panel as read-only state preview
  479. *
  480. * @return string
  481. */
  482. public function render($itemId, $size = '', $readOnly = false) {
  483. $result = '';
  484. $itemId = ubRouting::filters($itemId, 'mres');
  485. $currentStates = array();
  486. if (ubRouting::checkGet(self::ROUTE_ICONSIZE)) {
  487. $size = ubRouting::get(self::ROUTE_ICONSIZE, 'int');
  488. }
  489. //this itemid already have an stigma record
  490. if (isset($this->allStigmas[$itemId])) {
  491. $rawStates = explode(self::DELIMITER, $this->allStigmas[$itemId]['state']);
  492. $currentStates = array_flip($rawStates);
  493. unset($currentStates['']);
  494. }
  495. $containerName = 'ajStigma' . $this->scope . '_' . $itemId;
  496. $result .= wf_AjaxLoader($this->animated);
  497. $result .= wf_tag('div', false, '', 'id="' . $containerName . '"');
  498. //selecting and calling controller renderer method
  499. $rendererMethodName = self::RENDERER_PREFIX . ucfirst($this->renderer);
  500. if (method_exists($this, $rendererMethodName)) {
  501. $result .= $this->$rendererMethodName($itemId, $size, $readOnly, $currentStates, $containerName);
  502. } else {
  503. throw new Exception('EX_RENDERER_METHOD_NOT_EXISTS:' . $rendererMethodName);
  504. }
  505. $result .= wf_tag('div', true);
  506. $result .= wf_CleanDiv();
  507. return($result);
  508. }
  509. /**
  510. * Renders stigma states list or void if not set for some item
  511. *
  512. * @param string $itemId item ID to render control panel
  513. * @param int $size optional size of state icons
  514. *
  515. * @return string/void
  516. */
  517. public function renderItemStates($itemId, $size = '') {
  518. $result = '';
  519. $currentStates = array();
  520. //have this item existing stigma record?
  521. if (isset($this->allStigmas[$itemId])) {
  522. $rawStates = explode(self::DELIMITER, $this->allStigmas[$itemId]['state']);
  523. $currentStates = array_flip($rawStates);
  524. unset($currentStates['']);
  525. if (!empty($currentStates)) {
  526. foreach ($currentStates as $eachStateId => $index) {
  527. if (isset($this->states[$eachStateId])) {
  528. $stateLabel = __($this->states[$eachStateId]);
  529. $stateIcon = $this->getStateIcon($eachStateId);
  530. $result .= wf_img_sized($stateIcon, $stateLabel, $size) . ' ';
  531. }
  532. }
  533. }
  534. }
  535. return($result);
  536. }
  537. /**
  538. * Renders stigma current states as text string
  539. *
  540. * @param string $itemId item ID to render data
  541. * @param string $delimiter text delimiter between states
  542. * @param int $miniIcons icons size if required
  543. *
  544. * @return string
  545. */
  546. public function textRender($itemId, $delimiter = '', $miniIcons = '') {
  547. $result = '';
  548. $itemId = ubRouting::filters($itemId, 'mres');
  549. $currentStates = array();
  550. if (ubRouting::checkGet(self::ROUTE_ICONSIZE)) {
  551. $size = ubRouting::get(self::ROUTE_ICONSIZE, 'int');
  552. }
  553. //this itemid already have an stigma record
  554. if (isset($this->allStigmas[$itemId])) {
  555. $rawStates = explode(self::DELIMITER, $this->allStigmas[$itemId]['state']);
  556. $currentStates = array_flip($rawStates);
  557. unset($currentStates['']);
  558. }
  559. foreach ($currentStates as $stateId => $index) {
  560. if (!empty($stateId)) {
  561. $stateName = (isset($this->states[$stateId])) ? $this->states[$stateId] : $stateId;
  562. $stateLabel = __($stateName);
  563. $iconCode = '';
  564. if ($miniIcons) {
  565. $stateIcon = $this->getStateIcon($stateId);
  566. $iconCode = wf_img_sized($stateIcon, $stateLabel, $miniIcons) . ' ';
  567. }
  568. $result .= $iconCode . $stateLabel . $delimiter;
  569. }
  570. }
  571. return($result);
  572. }
  573. /**
  574. * Returns array of all item states as is (for isset checks)
  575. *
  576. * @param string $itemId
  577. *
  578. * @return array
  579. */
  580. public function getItemStates($itemId) {
  581. $result = array();
  582. if (isset($this->allStigmas[$itemId])) {
  583. if (!empty($this->allStigmas[$itemId]['state'])) {
  584. $itemStates = explode(self::DELIMITER, $this->allStigmas[$itemId]['state']);
  585. $result = array_flip($itemStates);
  586. unset($result['']);
  587. }
  588. }
  589. return($result);
  590. }
  591. /**
  592. * AJAX callbacks processing controller
  593. *
  594. * @param string $logging SYSTEM:[paramname] or TASKMAN:[paramname]
  595. *
  596. * @return void
  597. */
  598. public function stigmaController($logging = '') {
  599. if (ubRouting::checkGet(array(self::ROUTE_SCOPE, self::ROUTE_ITEMID, self::ROUTE_STATE))) {
  600. //my scope?
  601. if ($this->scope == ubRouting::get(self::ROUTE_SCOPE)) {
  602. $stigmaCtrl = new Stigma(ubRouting::get(self::ROUTE_SCOPE), ubRouting::get(self::ROUTE_ITEMID));
  603. //state modification callback?
  604. if (ubRouting::checkGet(self::ROUTE_STATE)) {
  605. if (!empty($logging)) {
  606. if (ispos($logging, 'TASKMAN:')) {
  607. $logging = str_replace('TASKMAN:', '', $logging);
  608. $stigmaCtrl->setTaskmanLogging($logging);
  609. }
  610. if (ispos($logging, 'SYSTEM:')) {
  611. $logging = str_replace('SYSTEM:', '', $logging);
  612. $stigmaCtrl->setSystemLogging($logging);
  613. }
  614. if (ispos($logging, 'CUSTOM:')) {
  615. $logging = str_replace('CUSTOM:', '', $logging);
  616. $stigmaCtrl->setCustomLogging($logging);
  617. }
  618. }
  619. $stigmaCtrl->saveState(ubRouting::get(self::ROUTE_ITEMID), ubRouting::get(self::ROUTE_STATE));
  620. }
  621. die($stigmaCtrl->render(ubRouting::get(self::ROUTE_ITEMID)));
  622. }
  623. }
  624. }
  625. /**
  626. * Creates new stigma in database
  627. *
  628. * @param string $itemId
  629. * @param string $state
  630. *
  631. * @return void
  632. */
  633. protected function createState($itemId, $state) {
  634. $this->stigmaDb->data('scope', $this->scope);
  635. $this->stigmaDb->data('itemid', $itemId);
  636. $this->stigmaDb->data('state', $state);
  637. $this->stigmaDb->data('date', curdatetime());
  638. $this->stigmaDb->data('admin', $this->myLogin);
  639. $this->stigmaDb->create();
  640. }
  641. /**
  642. * Sets some state string to selected item in current scope
  643. *
  644. * @param string $itemId
  645. * @param string $state
  646. *
  647. * @return void
  648. */
  649. protected function setState($itemId, $state) {
  650. $this->stigmaDb->data('state', $state);
  651. $this->stigmaDb->data('date', curdatetime());
  652. $this->stigmaDb->data('admin', $this->myLogin);
  653. $this->stigmaDb->where('scope', '=', $this->scope);
  654. $this->stigmaDb->where('itemid', '=', $itemId);
  655. $this->stigmaDb->save(true, true);
  656. }
  657. /**
  658. * Saves some new stigma state into database
  659. *
  660. * @param string $itemId
  661. * @param string $state
  662. *
  663. * @return void
  664. */
  665. public function saveState($itemId, $state) {
  666. $itemId = ubRouting::filters($itemId, 'mres');
  667. $state = ubRouting::filters($state, 'mres');
  668. //Item stigma already exists. Update it.
  669. if (isset($this->allStigmas[$itemId])) {
  670. $currentStates = $this->getItemStates($itemId);
  671. if ($this->type == 'radiolist') {
  672. //state is changed?
  673. if (!isset($currentStates[$state])) {
  674. $this->setState($itemId, $state);
  675. $this->logStigmaChange($itemId, 'Changed', $state);
  676. }
  677. }
  678. if ($this->type == 'checklist') {
  679. //uncheck already set state
  680. if (isset($currentStates[$state])) {
  681. $newStates = $currentStates;
  682. unset($newStates[$state]);
  683. $newStatesString = '';
  684. if (!empty($newStates)) {
  685. foreach ($newStates as $io => $each) {
  686. $newStatesString .= $io . self::DELIMITER;
  687. }
  688. }
  689. $this->logStigmaChange($itemId, 'Deleted', $state);
  690. } else {
  691. //update state with new one
  692. $newStates = $currentStates;
  693. $newStates[$state] = $state;
  694. $newStatesString = '';
  695. if (!empty($newStates)) {
  696. foreach ($newStates as $io => $each) {
  697. $newStatesString .= $io . self::DELIMITER;
  698. }
  699. }
  700. $this->logStigmaChange($itemId, 'Append', $state);
  701. }
  702. //saving new item state to database
  703. $this->setState($itemId, $newStatesString);
  704. }
  705. } else {
  706. //new stigma
  707. $this->createState($itemId, $state);
  708. $this->logStigmaChange($itemId, 'Created', $state);
  709. }
  710. //update internal structs
  711. $this->loadStigmas();
  712. }
  713. /**
  714. * Put logs data into database if required
  715. *
  716. * @param string $itemId
  717. * @param string $oldState
  718. * @param string $newState
  719. *
  720. * @return void
  721. */
  722. protected function logStigmaChange($itemId, $oldState, $newState) {
  723. if ($this->taskmanLogging) {
  724. $oldState = (isset($this->states[$oldState])) ? $this->states[$oldState] : $oldState;
  725. $newState = (isset($this->states[$newState])) ? $this->states[$newState] : $newState;
  726. ts_logTaskChange($itemId, $this->taskmanLogging, $oldState, $newState, false);
  727. }
  728. if ($this->systemLogging) {
  729. log_register('STIGMA ' . $this->scope . ' CHANGE [' . $itemId . '] `' . $this->systemLogging . '` ON `' . $newState . '`');
  730. }
  731. if ($this->customLogging) {
  732. $customLogDb = new NyanORM($this->customLogging);
  733. $customLogDb->data('date', curdatetime());
  734. $customLogDb->data('admin', $this->myLogin);
  735. $customLogDb->data('scope', $this->scope);
  736. $customLogDb->data('itemid', $itemId);
  737. $customLogDb->data('action', $oldState);
  738. $customLogDb->data('state', $newState);
  739. $customLogDb->create();
  740. }
  741. }
  742. /**
  743. * Checks for available states for some itemId in scope
  744. *
  745. * @param string $itemId
  746. *
  747. * @return bool
  748. */
  749. public function haveState($itemId) {
  750. $result = false;
  751. if (isset($this->allStigmas[$itemId])) {
  752. if (!empty($this->allStigmas[$itemId]['state'])) {
  753. $result = true;
  754. }
  755. }
  756. return($result);
  757. }
  758. /**
  759. * Returns array of all available states text labels as stateId=>textLabel
  760. *
  761. * @return array
  762. */
  763. public function getAllStates() {
  764. return($this->states);
  765. }
  766. /**
  767. * Returns all scopes for which stigmas available in database
  768. *
  769. * @return array
  770. */
  771. public function getAllScopes() {
  772. $result = array();
  773. $raw = $this->stigmaDb->getAll('scope', true, true);
  774. if (!empty($raw)) {
  775. foreach ($raw as $io => $each) {
  776. $result[$io] = $io;
  777. }
  778. }
  779. return($result);
  780. }
  781. /**
  782. * Returns report data by states in selected time range
  783. *
  784. * @param string $dateFrom
  785. * @param string $dateTo
  786. *
  787. * @return array
  788. */
  789. public function getReportData($dateFrom = '', $dateTo = '') {
  790. $result = array();
  791. $dateFilters = false;
  792. if (!empty($dateFrom) AND !empty($dateTo)) {
  793. $dateFilters = true;
  794. }
  795. if (!empty($this->allStigmas)) {
  796. foreach ($this->allStigmas as $eachItemId => $eachStigmaData) {
  797. $addToResult = true;
  798. if ($dateFilters) {
  799. $stigmaDate = $eachStigmaData['date'];
  800. if (zb_isDateBetween($dateFrom, $dateTo, $stigmaDate)) {
  801. $addToResult = true;
  802. } else {
  803. $addToResult = false;
  804. }
  805. }
  806. if ($addToResult) {
  807. $itemStates = $this->getItemStates($eachItemId);
  808. if (!empty($itemStates)) {
  809. foreach ($itemStates as $eachState => $eachIndex) {
  810. if (isset($result[$eachState])) {
  811. $result[$eachState]['count']++;
  812. } else {
  813. $result[$eachState]['count'] = 1;
  814. }
  815. if (isset($result[$eachState]['admins'][$eachStigmaData['admin']])) {
  816. $result[$eachState]['admins'][$eachStigmaData['admin']]++;
  817. } else {
  818. $result[$eachState]['admins'][$eachStigmaData['admin']] = 1;
  819. }
  820. $result[$eachState]['itemids'][$eachItemId] = $eachStigmaData['admin'];
  821. }
  822. }
  823. }
  824. }
  825. }
  826. return($result);
  827. }
  828. /**
  829. * Renders basic report on states applied on current scope
  830. *
  831. * @return string
  832. */
  833. public function renderBasicReport() {
  834. $result = '';
  835. $availStates = $this->getAllStates();
  836. $messages = new UbillingMessageHelper();
  837. //default date intervals setting
  838. $dateCurrentDay = curdate();
  839. $dateMonthBegin = curmonth() . '-01';
  840. $dateMonthEnd = curmonth() . '-' . date("t");
  841. $dateWeekBegin = date("Y-m-d", strtotime('monday this week'));
  842. $dateWeekEnd = date("Y-m-d", strtotime('sunday this week'));
  843. $dateYearBegin = curyear() . '-01-01';
  844. $dateYearEnd = curyear() . '-12-31';
  845. //getting report data
  846. $dataDay = $this->getReportData($dateCurrentDay, $dateCurrentDay);
  847. $dataWeek = $this->getReportData($dateWeekBegin, $dateWeekEnd);
  848. $dataMonth = $this->getReportData($dateMonthBegin, $dateMonthEnd);
  849. $dataYear = $this->getReportData($dateYearBegin, $dateYearEnd);
  850. $dataAllTime = $this->getReportData();
  851. if (!empty($availStates)) {
  852. $cells = wf_TableCell(__('Job'), '30%');
  853. $cells .= wf_TableCell(__('Day'));
  854. $cells .= wf_TableCell(__('Week'));
  855. $cells .= wf_TableCell(__('Month'));
  856. $cells .= wf_TableCell(__('Year'));
  857. $cells .= wf_TableCell(__('All time'));
  858. $rows = wf_TableRow($cells, 'row1');
  859. foreach ($availStates as $eachStateId => $eachStateDesc) {
  860. $stateLabel = __($eachStateDesc);
  861. $stateIcon = $this->getStateIcon($eachStateId);
  862. $dayCount = isset($dataDay[$eachStateId]['count']) ? $dataDay[$eachStateId]['count'] : 0;
  863. $weekCount = isset($dataWeek[$eachStateId]['count']) ? $dataWeek[$eachStateId]['count'] : 0;
  864. $monthCount = isset($dataMonth[$eachStateId]['count']) ? $dataMonth[$eachStateId]['count'] : 0;
  865. $yearCount = isset($dataYear[$eachStateId]['count']) ? $dataYear[$eachStateId]['count'] : 0;
  866. $allTimeCount = isset($dataAllTime[$eachStateId]['count']) ? $dataAllTime[$eachStateId]['count'] : 0;
  867. $cells = wf_TableCell(wf_img_sized($stateIcon, $stateLabel, '10') . ' ' . $stateLabel);
  868. $cells .= wf_TableCell($dayCount);
  869. $cells .= wf_TableCell($weekCount);
  870. $cells .= wf_TableCell($monthCount);
  871. $cells .= wf_TableCell($yearCount);
  872. $cells .= wf_TableCell($allTimeCount);
  873. $rows .= wf_TableRow($cells, 'row5');
  874. }
  875. $result .= wf_TableBody($rows, '100%', 0, 'sortable');
  876. } else {
  877. $result .= $messages->getStyledMessage(__('Nothing to show'), 'warning');
  878. }
  879. return($result);
  880. }
  881. }