/src/Dime/TimetrackerBundle/Controller/ActivitiesController.php

https://github.com/phpugl/Dime · PHP · 390 lines · 246 code · 49 blank · 95 comment · 35 complexity · daafa8399dee625a705d979aacce5a00 MD5 · raw file

  1. <?php
  2. namespace Dime\TimetrackerBundle\Controller;
  3. use FOS\RestBundle\View\View;
  4. use FOS\RestBundle\Controller\Annotations as FOS;
  5. use Doctrine\ORM\NoResultException;
  6. use Dime\TimetrackerBundle\Entity\Activity;
  7. use Dime\TimetrackerBundle\Entity\ActivityRepository;
  8. use Dime\TimetrackerBundle\Entity\Timeslice;
  9. use Dime\TimetrackerBundle\Entity\CustomerRepository;
  10. use Dime\TimetrackerBundle\Entity\ProjectRepository;
  11. use Dime\TimetrackerBundle\Entity\ServiceRepository;
  12. use Dime\TimetrackerBundle\Entity\Tag;
  13. use Dime\TimetrackerBundle\Entity\TagRepository;
  14. use Dime\TimetrackerBundle\Form\ActivityType;
  15. class ActivitiesController extends DimeController
  16. {
  17. /**
  18. * @var array allowed filter keys
  19. */
  20. protected $allowed_filter = array(
  21. 'date',
  22. 'active',
  23. 'customer',
  24. 'project',
  25. 'service',
  26. 'user',
  27. 'withTags',
  28. 'withoutTags'
  29. );
  30. /**
  31. * get activity repository
  32. *
  33. * @return ActivityRepository
  34. */
  35. protected function getActivityRepository()
  36. {
  37. return $this->getDoctrine()->getRepository('DimeTimetrackerBundle:Activity');
  38. }
  39. /**
  40. * get customer repository
  41. *
  42. * @return CustomerRepository
  43. */
  44. protected function getCustomerRepository()
  45. {
  46. return $this->getDoctrine()->getRepository('DimeTimetrackerBundle:Customer');
  47. }
  48. /**
  49. * get project repository
  50. *
  51. * @return ProjectRepository
  52. */
  53. protected function getProjectRepository()
  54. {
  55. return $this->getDoctrine()->getRepository('DimeTimetrackerBundle:Project');
  56. }
  57. /**
  58. * get activity repository
  59. *
  60. * @return ServiceRepository
  61. */
  62. protected function getServiceRepository()
  63. {
  64. return $this->getDoctrine()->getRepository('DimeTimetrackerBundle:Service');
  65. }
  66. /**
  67. * get a list of all activities
  68. *
  69. * [GET] /activities
  70. *
  71. * @FOS\Route("/activities")
  72. * @return View
  73. */
  74. public function getActivitiesAction()
  75. {
  76. $activities = $this->getActivityRepository();
  77. $activities->createCurrentQueryBuilder('a');
  78. // Filter
  79. $filter = $this->getRequest()->get('filter');
  80. if ($filter) {
  81. $activities->filter($this->cleanFilter($filter, $this->allowed_filter));
  82. }
  83. // Scope by current user
  84. if (!isset($filter['user'])) {
  85. $activities->scopeByField('user', $this->getCurrentUser()->getId());
  86. }
  87. // Sort by updatedAt and id
  88. $activities->getCurrentQueryBuilder()->addOrderBy('a.updatedAt', 'DESC');
  89. $activities->getCurrentQueryBuilder()->addOrderBy('a.id', 'DESC');
  90. // Pagination
  91. return $this->paginate(
  92. $activities->getCurrentQueryBuilder(),
  93. $this->getRequest()->get('limit'),
  94. $this->getRequest()->get('offset')
  95. );
  96. }
  97. /**
  98. * get an activity by its id
  99. *
  100. * [GET] /activities/{id}
  101. *
  102. * @param int $id
  103. * @return View
  104. */
  105. public function getActivityAction($id)
  106. {
  107. // find activity
  108. $activity = $this->getActivityRepository()->find($id);
  109. // check if it exists
  110. if ($activity) {
  111. // send array
  112. $view = $this->createView($activity);
  113. } else {
  114. // activity does not exists send 404
  115. $view = $this->createView("Activity does not exist.", 404);
  116. }
  117. return $view;
  118. }
  119. /**
  120. * create a new activity
  121. *
  122. * [POST] /activities
  123. *
  124. * @return View
  125. */
  126. public function postActivitiesAction()
  127. {
  128. // create new activity entity
  129. $activity = new Activity();
  130. // convert json to assoc array from request content
  131. $data = json_decode($this->getRequest()->getContent(), true);
  132. if (isset($data['parse'])) {
  133. // Run parser
  134. $result = $this->parse($data['parse']);
  135. if (isset($data['date'])) {
  136. $date = new \DateTime($data['date']);
  137. } else {
  138. $date = new \DateTime();
  139. }
  140. // create new activity and timeslice entity
  141. $activity = new Activity();
  142. $activity->setUser($this->getCurrentUser());
  143. if (isset($result['customer'])) {
  144. try {
  145. $customer = $this->getCustomerRepository()
  146. ->createCurrentQueryBuilder('c')
  147. ->scopeByField('user', $this->getCurrentUser()->getId())
  148. ->scopeByField('alias', $result['customer'])
  149. ->getCurrentQueryBuilder()
  150. ->setMaxResults(1)
  151. ->getQuery()->getSingleResult();
  152. $activity->setCustomer($customer);
  153. } catch (NoResultException $e) {
  154. }
  155. }
  156. if (isset($result['project'])) {
  157. try {
  158. $project = $this->getProjectRepository()
  159. ->createCurrentQueryBuilder('p')
  160. ->scopeByField('user', $this->getCurrentUser()->getId())
  161. ->scopeByField('alias', $result['project'])
  162. ->getCurrentQueryBuilder()
  163. ->setMaxResults(1)
  164. ->getQuery()->getSingleResult();
  165. $activity->setProject($project);
  166. // Auto set customer because of direct relation to project
  167. if ($activity->getCustomer() == null) {
  168. $activity->setCustomer($project->getCustomer());
  169. }
  170. } catch (NoResultException $e) {
  171. }
  172. }
  173. if (isset($result['service'])) {
  174. try {
  175. $service = $this->getServiceRepository()
  176. ->createCurrentQueryBuilder('p')
  177. ->scopeByField('user', $this->getCurrentUser()->getId())
  178. ->scopeByField('alias', $result['service'])
  179. ->getCurrentQueryBuilder()
  180. ->setMaxResults(1)
  181. ->getQuery()->getSingleResult();
  182. $activity->setService($service);
  183. } catch (NoResultException $e) {
  184. }
  185. }
  186. if (isset($result['tags']) && !empty($result['tags'])) {
  187. foreach ($result['tags'] as $tagname) {
  188. try {
  189. $tag = $this->getTagRepository()
  190. ->createCurrentQueryBuilder('t')
  191. ->scopeByField('user', $this->getCurrentUser()->getId())
  192. ->scopeByField('name', $tagname)
  193. ->getCurrentQueryBuilder()
  194. ->setMaxResults(1)
  195. ->getQuery()->getSingleResult();
  196. } catch (NoResultException $e) {
  197. $tag = null;
  198. }
  199. if ($tag == null) {
  200. $tag = new Tag();
  201. $tag->setName($tagname);
  202. $tag->setUser($this->getCurrentUser());
  203. }
  204. $activity->addTag($tag);
  205. }
  206. }
  207. if (isset($result['description'])) {
  208. $activity->setDescription($result['description']);
  209. }
  210. // create timeslice
  211. $timeslice = new Timeslice();
  212. $timeslice->setActivity($activity);
  213. $timeslice->setUser($this->getCurrentUser());
  214. $activity->addTimeslice($timeslice);
  215. if (isset($result['range']) || isset($result['duration'])) {
  216. // process time range
  217. if (isset($result['range'])) {
  218. $range = $result['range'];
  219. if (empty($range['stop'])) {
  220. $start = new \DateTime($range['start']);
  221. $stop = new \DateTime('now');
  222. } elseif (empty($range['start'])) {
  223. $start = new \DateTime('now');
  224. $stop = new \DateTime($range['stop']);
  225. } elseif (!empty($range['start']) && !empty($range['stop'])) {
  226. $start = new \DateTime($range['start']);
  227. $stop = new \DateTime($range['stop']);
  228. }
  229. $start->setDate($date->format('Y'), $date->format('m'), $date->format('d'));
  230. $stop->setDate($date->format('Y'), $date->format('m'), $date->format('d'));
  231. $timeslice->setStartedAt($start);
  232. $timeslice->setStoppedAt($stop);
  233. } else {
  234. // track date for duration
  235. $date->setTime(0, 0, 0);
  236. $timeslice->setStartedAt($date);
  237. $timeslice->setStoppedAt($date);
  238. }
  239. // process duration
  240. if (isset($result['duration'])) {
  241. if (empty($result['duration']['sign'])) {
  242. $timeslice->setDuration($result['duration']['number']);
  243. } else {
  244. if ($result['duration']['sign'] == '-') {
  245. $timeslice->setDuration($timeslice->getCurrentDuration() - $result['duration']['number']);
  246. } else {
  247. $timeslice->setDuration($timeslice->getCurrentDuration() + $result['duration']['number']);
  248. }
  249. }
  250. }
  251. } else {
  252. // start a new timeslice with date 'now'
  253. $timeslice->setStartedAt(new \DateTime('now'));
  254. }
  255. // save change to database
  256. $em = $this->getDoctrine()->getManager();
  257. $em->persist($activity);
  258. $em->flush();
  259. $em->refresh($activity);
  260. $view = $this->createView($activity);
  261. } else {
  262. // create activity form
  263. $form = $this->createForm(new ActivityType($this->getDoctrine()->getManager(), $this->getCurrentUser()), $activity);
  264. $view = $this->saveForm($form, $data);
  265. }
  266. return $view;
  267. }
  268. /**
  269. * modify an activity by its id
  270. *
  271. * [PUT] /activities/{id}
  272. *
  273. * @param string $id
  274. * @return View
  275. */
  276. public function putActivitiesAction($id)
  277. {
  278. // find activity
  279. $activity = $this->getActivityRepository()->find($id);
  280. // check if it exists
  281. if ($activity) {
  282. $data = json_decode($this->getRequest()->getContent(), true);
  283. // create form, decode request and save it if valid
  284. $view = $this->saveForm(
  285. $this->createForm(new ActivityType($this->getDoctrine()->getManager(), $this->getCurrentUser()), $activity),
  286. $data
  287. );
  288. } else {
  289. // activity does not exists send 404
  290. $view = $this->createView("Activity does not exist.", 404);
  291. }
  292. return $view;
  293. }
  294. /**
  295. * delete an activity by its id
  296. * [DELETE] /activities/{id}
  297. *
  298. * @param int $id
  299. * @return View
  300. */
  301. public function deleteActivitiesAction($id)
  302. {
  303. // find activity
  304. $activity = $this->getActivityRepository()->find($id);
  305. // check if it exists
  306. if ($activity) {
  307. // remove service
  308. $em = $this->getDoctrine()->getManager();
  309. $em->remove($activity);
  310. $em->flush();
  311. // send status message
  312. $view = $this->createView("Activity has been removed.");
  313. } else {
  314. // activity does not exists send 404
  315. $view = $this->createView("Activity does not exist.", 404);
  316. }
  317. return $view;
  318. }
  319. /**
  320. * Parse data and create an array output
  321. * @param string $data
  322. * @return array
  323. */
  324. protected function parse($data)
  325. {
  326. $result = array();
  327. $parsers = array(
  328. '\Dime\TimetrackerBundle\Parser\TimerangeParser',
  329. '\Dime\TimetrackerBundle\Parser\DurationParser',
  330. '\Dime\TimetrackerBundle\Parser\ActivityRelationParser',
  331. '\Dime\TimetrackerBundle\Parser\ActivityDescriptionParser'
  332. );
  333. foreach ($parsers as $parser) {
  334. $p = new $parser();
  335. $result = $p->setResult($result)->run($data);
  336. $data = $p->clean($data);
  337. unset($p);
  338. }
  339. return $result;
  340. }
  341. }