AuditDataService.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. <?php
  2. namespace AuditBundle\Services;
  3. use Doctrine\DBAL\Connection;
  4. use Doctrine\ORM\EntityManagerInterface;
  5. use SimpleThings\EntityAudit\AuditManager;
  6. use SimpleThings\EntityAudit\AuditReader;
  7. use SimpleThings\EntityAudit\Revision;
  8. class AuditDataService
  9. {
  10. /**
  11. * @var Connection
  12. */
  13. private $connection;
  14. /**
  15. * @var AuditReader
  16. */
  17. private $reader;
  18. /**
  19. * @var AuditManager
  20. */
  21. private $auditManager;
  22. /**
  23. * @var EntityManagerInterface
  24. */
  25. private $entityManager;
  26. /**
  27. * @param Connection $connection
  28. * @param AuditReader $reader
  29. * @param AuditManager $auditManager
  30. * @param EntityManagerInterface $entityManager
  31. */
  32. public function __construct(Connection $connection, AuditReader $reader, AuditManager $auditManager, EntityManagerInterface $entityManager)
  33. {
  34. $this->connection = $connection;
  35. $this->reader = $reader;
  36. $this->auditManager = $auditManager;
  37. $this->entityManager = $entityManager;
  38. }
  39. /**
  40. * Get all revisions filtered for user and timestamp
  41. *
  42. * @param string $user
  43. * @param DateTime $dateFrom
  44. * @param DateTime $dateTo
  45. * @param int $page
  46. *
  47. * @return type
  48. */
  49. public function getRevisionsData($user, $dateFrom, $dateTo, $page)
  50. {
  51. //Set default page
  52. $show = 25;
  53. if (!$page) {
  54. $page = 1;
  55. }
  56. $sqlct = "SELECT Count(id) AS Total FROM revisions WHERE (id <> 0 AND username <> '') ";
  57. foreach ($user as $key => $usr) {
  58. if ($key == 0) {
  59. $sqlct .= "AND username LIKE '%{$usr}%' ";
  60. } else {
  61. $sqlct .= "OR username LIKE '%{$usr}%' ";
  62. }
  63. }
  64. if ($dateFrom != '') {
  65. $sqlct .= "AND (timestamp >= '{$dateFrom} 00:00:00') ";
  66. }
  67. if ($dateTo != '') {
  68. $sqlct .= "AND (timestamp <= '{$dateTo} 23:59:59') ";
  69. }
  70. // Sql for get data
  71. $sqlrev = "SELECT timestamp,id AS rev FROM revisions WHERE (id <> 0 AND username <> '') ";
  72. foreach ($user as $key => $usr) {
  73. if ($key == 0) {
  74. $sqlrev .= "AND username LIKE '%{$usr}%' ";
  75. } else {
  76. $sqlrev .= "OR username LIKE '%{$usr}%' ";
  77. }
  78. }
  79. if ($dateFrom != '') {
  80. $sqlrev .= "AND (timestamp >= '{$dateFrom} 00:00:00') ";
  81. }
  82. if ($dateTo != '') {
  83. $sqlrev .= "AND (timestamp <= '{$dateTo} 23:59:59') ";
  84. }
  85. // Count results
  86. $regs = $this->connection->fetchColumn($sqlct, array(1), 0);
  87. // Set pagination
  88. $from = ($page - 1) * $show;
  89. $To = ($page) * $show;
  90. if ($To > $regs) {
  91. $To = $regs;
  92. }
  93. $sqlrev .= "ORDER BY timestamp DESC LIMIT " . $from . ", " . $To;
  94. $query_result = $this->connection->fetchAll($sqlrev);
  95. $results_processed_changes = $this->results_with_processed_changes($query_result);
  96. $tdata = array(
  97. 'regs' => $regs,
  98. 'revisions' => $results_processed_changes,
  99. );
  100. return ($tdata);
  101. }
  102. /**
  103. * @return array
  104. */
  105. public function getRevisionUsers()
  106. {
  107. $query = "SELECT DISTINCT(SUBSTRING_INDEX(username, '(', 1)) as username FROM revisions ORDER BY username ASC;";
  108. $usernames = array();
  109. foreach ($this->connection->fetchAll($query) as $username) {
  110. $usernames[$username['username']] = $username['username'];
  111. }
  112. return $usernames;
  113. }
  114. /**
  115. * Get all revisions with the changes processed
  116. *
  117. * @param array $query_result
  118. *
  119. * @return array
  120. */
  121. public function results_with_processed_changes($query_result)
  122. {
  123. $param_query_result = $query_result;
  124. foreach ($param_query_result as $key => &$data) {
  125. $entity_results = array();
  126. $data['rev_data'] = $this->reader->findRevision($data['rev']);
  127. $data['rev_entities_data'] = $this->reader->findEntitiesChangedAtRevision($data['rev']);
  128. #Get entity of the revision
  129. $entity_revs = $data['rev_entities_data'];
  130. foreach ($entity_revs as $result) {
  131. $changes_all = array();
  132. #Get all revisions for each class in table revision
  133. $history_for_class = $this->reader->findRevisions($result->getClassName(), $result->getId());
  134. foreach ($history_for_class as $rev_history) {
  135. if ($rev_history->getRev() < $data['rev']) {
  136. $diff = $this->reader->diff($result->getClassName(), $result->getId(), $rev_history->getRev(), $data['rev']);
  137. foreach ($diff as $field => $value) {
  138. if ($value['old'] != "") {
  139. if (!is_a($value['old'], 'DateTime')) {
  140. $changes = array();
  141. $changes['field'] = $field;
  142. $changes['old'] = $value['old'];
  143. $changes['new'] = $value['new'];
  144. array_push($changes_all, $changes);
  145. }
  146. }
  147. }
  148. break;
  149. }
  150. }
  151. }
  152. if (!isset($changes_all)) {
  153. $changes_all = array();
  154. }
  155. $data['changed_field'] = $changes_all;
  156. }
  157. return $param_query_result;
  158. }
  159. /**
  160. * Applied diff between revisions
  161. *
  162. * @param string $className
  163. * @param int $id
  164. * @param Revision $oldRev
  165. * @param Revision $newRev
  166. *
  167. * @return array
  168. */
  169. public function diff($className, $id, $oldRev, $newRev)
  170. {
  171. return $this->reader->diff($className, $id, $oldRev, $newRev);
  172. }
  173. /**
  174. * Get data of a revision
  175. *
  176. * @param string $className
  177. * @param int $id
  178. * @param Revision $rev
  179. *
  180. * @return array
  181. */
  182. public function viewRevision($className, $id, $rev)
  183. {
  184. $entity = $this->reader->find($className, $id, $rev);
  185. return array(
  186. 'rev_details' => $this->reader->getEntityValues($className, $entity),
  187. 'rev_revisions' => $this->reader->findRevisions($className, $id),
  188. 'revdata' => $this->reader->findRevision($rev),
  189. );
  190. }
  191. /**
  192. * @return array
  193. */
  194. public function getEntities()
  195. {
  196. $mdFactory = $this->auditManager->getMetadataFactory();
  197. $meta = $this->entityManager->getMetadataFactory()->getAllMetadata();
  198. $entities = array();
  199. foreach ($meta as $m) {
  200. $entities[$m->getName()] = $m->table['name'];
  201. }
  202. ksort($entities);
  203. foreach ($entities as $key => $entityName) {
  204. if (!$mdFactory->isAudited($key)) {
  205. unset($entities[$key]);
  206. }
  207. }
  208. return $entities;
  209. }
  210. /**
  211. * @return array
  212. */
  213. public function getColumns()
  214. {
  215. $columns = array();
  216. $meta = $this->entityManager->getMetadataFactory()->getAllMetadata();
  217. foreach ($meta as $m) {
  218. $columns[$m->getName()] = $m->getColumnNames();
  219. }
  220. return $columns;
  221. }
  222. /**
  223. * @param array $data
  224. *
  225. * @return array
  226. */
  227. public function getResults($data)
  228. {
  229. $entities = $this->getEntities();
  230. $pages = 1;
  231. $users = array();
  232. $types = array();
  233. extract($data); // retorna la data del filter form
  234. // var_dump($page);
  235. // die;
  236. $entity = array_search($entity, $entities);
  237. $from = $this->buildFrom($entity);
  238. $where = $this->buildWhere($entity, $users, $types, $idx, $dateFrom, $dateTo, $searchValue);
  239. $sql_cnt = $this->buildSelect($entity, true) . $from . $where;
  240. $count = $this->connection->query($sql_cnt)->fetchAll()[0]['total'];
  241. $sql = $this->buildSelect($entity) . $from . $where;
  242. $sql .= "ORDER BY R.timestamp DESC ";
  243. if ($resxpage != "inf") {
  244. $pages = ceil(($count / floatval($resxpage)));
  245. $from = ($page - 1) * $resxpage;
  246. $to = ($page) * $resxpage;
  247. $sql .= "LIMIT {$from},{$to}";
  248. }
  249. return array(
  250. 'result' => $this->connection->query($sql)->fetchAll(),
  251. 'count' => $count,
  252. 'page' => $page,
  253. 'pages' => $pages,
  254. );
  255. }
  256. /**
  257. * @param string $entity
  258. * @param bool $count
  259. *
  260. * @return string
  261. */
  262. private function buildSelect($entity, $count = false)
  263. {
  264. $select = 'SELECT C.rev, C.id, C.revtype, R.username, R.timestamp ';
  265. if ($count) {
  266. $select = 'SELECT COUNT(*) as total ';
  267. }
  268. $columns = $this->getColumns();
  269. foreach ($columns[$entity] as $column) {
  270. $select .= ", C." . $column . " ";
  271. }
  272. return $select;
  273. }
  274. /**
  275. * @param string $entity
  276. *
  277. * @return string
  278. */
  279. private function buildFrom($entity)
  280. {
  281. $entities = $this->getEntities();
  282. return "FROM `{$entities[$entity]}_audit` AS C INNER JOIN `revisions` AS R ON C.rev = R.id ";
  283. }
  284. /**
  285. * @param string $entity
  286. * @param array $users
  287. * @param array $types
  288. * @param int $idx
  289. * @param string $dateFrom
  290. * @param string $dateTo
  291. * @param string $searchValue
  292. *
  293. * @return string
  294. */
  295. private function buildWhere($entity, $users = null, $types = null, $idx = null, $dateFrom = null, $dateTo = null, $searchValue = null)
  296. {
  297. $where = '';
  298. $columns = $this->getColumns();
  299. if ($users || $types || $idx || $dateFrom || $dateTo || $searchValue) {
  300. $where .= 'WHERE C.id > 0 ';
  301. if ($users) {
  302. foreach ($users as $key => $user) {
  303. if ($key == 0) {
  304. $where .= "AND (R.username = '{$user}' ";
  305. } else {
  306. $where .= "OR R.username = '{$user}' ";
  307. }
  308. }
  309. $where .= ') ';
  310. }
  311. if ($types) {
  312. foreach ($types as $key => $type) {
  313. if ($key == 0) {
  314. $where .= "AND (C.revtype = '{$type}' ";
  315. } else {
  316. $where .= "OR C.revtype = '{$type}' ";
  317. }
  318. }
  319. $where .= ') ';
  320. }
  321. if ($idx) {
  322. $where .= "AND (C.id = '{$idx}') ";
  323. }
  324. if ($dateFrom && $dateTo) {
  325. $where .= " AND R.timestamp BETWEEN '{$dateFrom->format('Y-m-d')} 00:00:00' AND '{$dateTo->format('Y-m-d')} 23:59:59' ";
  326. }
  327. if ($searchValue) {
  328. foreach ($columns[$entity] as $key => $col) {
  329. if ($key == 0) {
  330. $where .= " AND (C.{$col} LIKE '{$searchValue}' ";
  331. } else {
  332. $where .= " OR C.{$col} LIKE '{$searchValue}' ";
  333. }
  334. }
  335. $where .= ') ';
  336. }
  337. }
  338. return $where;
  339. }
  340. }