AuditDataService.php 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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. use SimpleThings\EntityAudit\Exception\NoRevisionFoundException;
  9. class AuditDataService
  10. {
  11. /**
  12. * @var Connection
  13. */
  14. private $connection;
  15. /**
  16. * @var AuditReader
  17. */
  18. private $reader;
  19. /**
  20. * @var AuditManager
  21. */
  22. private $auditManager;
  23. /**
  24. * @var EntityManagerInterface
  25. */
  26. private $entityManager;
  27. /**
  28. * @param Connection $connection
  29. * @param AuditReader $reader
  30. * @param AuditManager $auditManager
  31. * @param EntityManagerInterface $entityManager
  32. */
  33. public function __construct(Connection $connection, AuditReader $reader, AuditManager $auditManager, EntityManagerInterface $entityManager)
  34. {
  35. $this->connection = $connection;
  36. $this->reader = $reader;
  37. $this->auditManager = $auditManager;
  38. $this->entityManager = $entityManager;
  39. }
  40. /**
  41. * @return array
  42. */
  43. public function getRevisionUsers()
  44. {
  45. $query = "SELECT DISTINCT(SUBSTRING_INDEX(username, '(', 1)) as username FROM revisions ORDER BY username ASC;";
  46. $usernames = array();
  47. foreach ($this->connection->fetchAll($query) as $username) {
  48. $usernames[$username['username']] = $username['username'];
  49. }
  50. return $usernames;
  51. }
  52. /**
  53. * Applied diff between revisions
  54. *
  55. * @param string $className
  56. * @param int $id
  57. * @param Revision $oldRev
  58. * @param Revision $newRev
  59. *
  60. * @return array
  61. */
  62. public function diff($className, $id, $oldRev, $newRev)
  63. {
  64. return $this->reader->diff($className, $id, $oldRev, $newRev);
  65. }
  66. /**
  67. * Get data of a revision
  68. *
  69. * @param string $className
  70. * @param int $id
  71. * @param Revision $rev
  72. *
  73. * @return array
  74. */
  75. public function viewRevision($className, $id, $rev)
  76. {
  77. $rev_details = [];
  78. $rev_revisions = [];
  79. $revdata = [];
  80. try {
  81. $entity = $this->reader->find($className, $id, $rev);
  82. } catch(NoRevisionFoundException $e) {
  83. $entity = $this->entityManager->getRepository($className)->find($id);
  84. }
  85. if ($entity) {
  86. $rev_details = $this->reader->getEntityValues($className, $entity);
  87. $rev_revisions = $this->reader->findRevisions($className, $id);
  88. $revdata = $this->reader->findRevision($rev);
  89. }
  90. return [
  91. 'rev_details' => $rev_details,
  92. 'rev_revisions' => $rev_revisions,
  93. 'revdata' => $revdata,
  94. ];
  95. }
  96. /**
  97. * @return array
  98. */
  99. public function getEntities()
  100. {
  101. $mdFactory = $this->auditManager->getMetadataFactory();
  102. $meta = $this->entityManager->getMetadataFactory()->getAllMetadata();
  103. $entities = array();
  104. foreach ($meta as $m) {
  105. $entities[$m->getName()] = $m->table['name'];
  106. }
  107. ksort($entities);
  108. foreach ($entities as $key => $entityName) {
  109. if (!$mdFactory->isAudited($key)) {
  110. unset($entities[$key]);
  111. }
  112. }
  113. return $entities;
  114. }
  115. /**
  116. * @return array
  117. */
  118. public function getColumns()
  119. {
  120. $columns = array();
  121. $meta = $this->entityManager->getMetadataFactory()->getAllMetadata();
  122. foreach ($meta as $m) {
  123. $columns[$m->getName()] = $m->getColumnNames();
  124. }
  125. return $columns;
  126. }
  127. /**
  128. * @param array $data
  129. *
  130. * @return array
  131. */
  132. public function getResults($data)
  133. {
  134. $entities = $this->getEntities();
  135. $pages = 1;
  136. $users = array();
  137. $types = array();
  138. extract($data); // retorna la data del filter form
  139. $entity = array_search($entity, $entities);
  140. $from = $this->buildFrom($entity);
  141. $where = $this->buildWhere($entity, $users, $types, $idx, $dateFrom, $dateTo, $searchValue);
  142. $groupBy = $this->buildGroupBy($entity);
  143. $sql_cnt = $this->buildSelect($entity, true) . $from . $where . $groupBy;
  144. $fetchAll = $this->connection->query($sql_cnt)->fetchAll();
  145. $count = 0;
  146. foreach ($fetchAll as $row) {
  147. $count += isset($row['total']) ? $row['total'] : 0;
  148. }
  149. $sql = $this->buildSelect($entity) . $from . $where . $groupBy;
  150. $sql .= " ORDER BY R.timestamp DESC ";
  151. if(is_null($resxpage)) $resxpage = 10;
  152. if ($resxpage != "inf") {
  153. $pages = ceil(($count / floatval($resxpage)));
  154. $from = ($page - 1) * $resxpage;
  155. //$to = ($page) * $resxpage;
  156. $sql .= " LIMIT {$from},{$resxpage} ";
  157. }
  158. return array(
  159. 'result' => $this->connection->query($sql)->fetchAll(),
  160. 'count' => $count,
  161. 'page' => $page,
  162. 'pages' => $pages,
  163. );
  164. }
  165. /**
  166. * @param string $entity
  167. * @param bool $count
  168. *
  169. * @return string
  170. */
  171. private function buildSelect($entity, $count = false)
  172. {
  173. $entities = $this->getEntities();
  174. $primaryKeyQuery = "SHOW KEYS FROM `{$entities[$entity]}` WHERE Key_name = 'PRIMARY';";
  175. $primaryKey = $this->connection->fetchAll($primaryKeyQuery);
  176. $id = 'id';
  177. if (isset($primaryKey[0])) {
  178. $id = $primaryKey[0]['Column_name'];
  179. }
  180. $select = "SELECT C.rev, C.{$id} as id, C.revtype, R.username, R.timestamp ";
  181. if ($count) {
  182. $select = 'SELECT COUNT(*) as total ';
  183. }
  184. $columns = $this->getColumns();
  185. foreach ($columns[$entity] as $column) {
  186. $select .= ", C." . $column . " ";
  187. }
  188. return $select;
  189. }
  190. /**
  191. * @param string $entity
  192. *
  193. * @return string
  194. */
  195. private function buildFrom($entity)
  196. {
  197. $entities = $this->getEntities();
  198. return "FROM `{$entities[$entity]}_audit` AS C INNER JOIN `revisions` AS R ON C.rev = R.id ";
  199. }
  200. /**
  201. * @param string $entity
  202. * @param array $users
  203. * @param array $types
  204. * @param int $idx
  205. * @param string $dateFrom
  206. * @param string $dateTo
  207. * @param string $searchValue
  208. *
  209. * @return string
  210. */
  211. private function buildWhere($entity, $users = null, $types = null, $idx = null, $dateFrom = null, $dateTo = null, $searchValue = null)
  212. {
  213. $where = '';
  214. $columns = $this->getColumns();
  215. if ($users || $types || $idx || $dateFrom || $dateTo || $searchValue) {
  216. $where .= 'WHERE C.id > 0 ';
  217. if ($users) {
  218. foreach ($users as $key => $user) {
  219. if ($key == 0) {
  220. $where .= "AND (R.username = '{$user}' ";
  221. } else {
  222. $where .= "OR R.username = '{$user}' ";
  223. }
  224. }
  225. $where .= ') ';
  226. }
  227. if ($types) {
  228. foreach ($types as $key => $type) {
  229. if ($key == 0) {
  230. $where .= "AND (C.revtype = '{$type}' ";
  231. } else {
  232. $where .= "OR C.revtype = '{$type}' ";
  233. }
  234. }
  235. $where .= ') ';
  236. }
  237. if ($idx) {
  238. $where .= "AND (C.id = '{$idx}') ";
  239. }
  240. if ($dateFrom && $dateTo) {
  241. $where .= " AND R.timestamp BETWEEN '{$dateFrom->format('Y-m-d')} 00:00:00' AND '{$dateTo->format('Y-m-d')} 23:59:59' ";
  242. }elseif($dateFrom) {
  243. $where .= " AND R.timestamp > '{$dateFrom->format('Y-m-d')} 00:00:00' ";
  244. }elseif($dateTo) {
  245. $where .= " AND R.timestamp < '{$dateTo->format('Y-m-d')} 23:59:59' ";
  246. }
  247. if ($searchValue) {
  248. foreach ($columns[$entity] as $key => $col) {
  249. if ($key == 0) {
  250. $where .= " AND (C.{$col} LIKE '{$searchValue}' ";
  251. } else {
  252. $where .= " OR C.{$col} LIKE '{$searchValue}' ";
  253. }
  254. }
  255. $where .= ') ';
  256. }
  257. }
  258. return $where;
  259. }
  260. /**
  261. * @return string
  262. */
  263. private function buildGroupBy($entity)
  264. {
  265. $columns = $this->getColumns();
  266. $groupBy[] = 'C.rev';
  267. foreach ($columns[$entity] as $column) {
  268. $groupBy[] = "C.{$column}";
  269. }
  270. $groupBy = implode(', ', $groupBy);
  271. $groupBy = " GROUP BY {$groupBy} ";
  272. return $groupBy;
  273. }
  274. }