render('price-tier/list.html.twig'); } /** * @IsGranted("price_tier.list") */ public function datatableRows(Request $req) { // get query builder $qb = $this->getDoctrine() ->getRepository(PriceTier::class) ->createQueryBuilder('q'); // get datatable params $datatable = $req->request->get('datatable'); // count total records $tquery = $qb->select('COUNT(q)'); $this->setQueryFilters($datatable, $tquery); $total = $tquery->getQuery() ->getSingleScalarResult(); // get current page number $page = $datatable['pagination']['page'] ?? 1; $perpage = $datatable['pagination']['perpage']; $offset = ($page - 1) * $perpage; // add metadata $meta = [ 'page' => $page, 'perpage' => $perpage, 'pages' => ceil($total / $perpage), 'total' => $total, 'sort' => 'asc', 'field' => 'id' ]; // build query $query = $qb->select('q'); $this->setQueryFilters($datatable, $query); // check if sorting is present, otherwise use default if (isset($datatable['sort']['field']) && !empty($datatable['sort']['field'])) { $order = $datatable['sort']['sort'] ?? 'asc'; $query->orderBy('q.' . $datatable['sort']['field'], $order); } else { $query->orderBy('q.id', 'asc'); } // get rows for this page $obj_rows = $query->setFirstResult($offset) ->setMaxResults($perpage) ->getQuery() ->getResult(); // process rows $rows = []; foreach ($obj_rows as $orow) { // add row data $row['id'] = $orow->getID(); $row['name'] = $orow->getName(); // add row metadata $row['meta'] = [ 'update_url' => '', 'delete_url' => '' ]; // add crud urls if ($this->isGranted('price_tier.update')) $row['meta']['update_url'] = $this->generateUrl('price_tier_update_form', ['id' => $row['id']]); if ($this->isGranted('service_offering.delete')) $row['meta']['delete_url'] = $this->generateUrl('price_tier_delete', ['id' => $row['id']]); $rows[] = $row; } // response return $this->json([ 'meta' => $meta, 'data' => $rows ]); } /** * @Menu(selected="price_tier.list") * @IsGranted("price_tier.add") */ public function addForm(EntityManagerInterface $em) { $pt = new PriceTier(); // get the supported areas $sets = $this->generateFormSets($em); $params = [ 'obj' => $pt, 'sets' => $sets, 'mode' => 'create', ]; // response return $this->render('price-tier/form.html.twig', $params); } /** * @IsGranted("price_tier.add") */ public function addSubmit(Request $req, EntityManagerInterface $em, ValidatorInterface $validator) { // initialize error list $error_array = []; $pt = new PriceTier(); $error_array = $this->validateRequest($em, $req); $this->setObject($pt, $req); // validate $errors = $validator->validate($pt); // add errors to list foreach ($errors as $error) { $error_array[$error->getPropertyPath()] = $error->getMessage(); } // check if any errors were found if (!empty($error_array)) { // return validation failure response return $this->json([ 'success' => false, 'errors' => $error_array ], 422); } // validated! save the entity $em->persist($pt); // set the price tier id for the selected supported areas $this->updateSupportedAreas($em, $pt, $req); $em->flush(); // return successful response return $this->json([ 'success' => 'Changes have been saved!' ]); } /** * @Menu(selected="price_tier_list") * @ParamConverter("pt", class="App\Entity\PriceTier") * @IsGranted("price_tier.update") */ public function updateForm($id, EntityManagerInterface $em, PriceTier $pt) { // get the supported areas $sets = $this->generateFormSets($em, $pt); $params = [ 'obj' => $pt, 'sets' => $sets, 'mode' => 'update', ]; // response return $this->render('price-tier/form.html.twig', $params); } /** * @ParamConverter("pt", class="App\Entity\PriceTier") * @IsGranted("price_tier.update") */ public function updateSubmit(Request $req, EntityManagerInterface $em, ValidatorInterface $validator, PriceTier $pt) { // initialize error list $error_array = []; // clear supported areas of price tier $this->clearPriceTierSupportedAreas($em, $pt); $error_array = $this->validateRequest($em, $req); $this->setObject($pt, $req); // validate $errors = $validator->validate($pt); // add errors to list foreach ($errors as $error) { $error_array[$error->getPropertyPath()] = $error->getMessage(); } // check if any errors were found if (!empty($error_array)) { // return validation failure response return $this->json([ 'success' => false, 'errors' => $error_array ], 422); } // set the price tier id for the selected supported areas $this->updateSupportedAreas($em, $pt, $req); // validated! save the entity $em->flush(); // return successful response return $this->json([ 'success' => 'Changes have been saved!' ]); } /** * @ParamConverter("pt", class="App\Entity\PriceTier") * @IsGranted("price_tier.delete") */ public function deleteSubmit(EntityManagerInterface $em, PriceTier $pt) { // clear supported areas of price tier $this->clearPriceTierSupportedAreas($em, $pt); // delete this object $em->remove($pt); $em->flush(); // response $response = new Response(); $response->setStatusCode(Response::HTTP_OK); $response->send(); } protected function validateRequest(EntityManagerInterface $em, Request $req) { // get areas $areas = $req->request->get('areas'); // check if no areas selected aka empty if (!empty($areas)) { foreach ($areas as $area_id) { $supported_area = $em->getRepository(SupportedArea::class)->find($area_id); if ($supported_area == null) return ['areas' => 'Invalid area']; // check if supported area already belongs to a price tier if ($supported_area->getPriceTier() != null) return ['areas' => 'Area already belongs to a price tier.']; } } return null; } protected function setObject(PriceTier $obj, Request $req) { // clear supported areas first $obj->clearSupportedAreas(); $obj->setName($req->request->get('name')); } protected function clearPriceTierSupportedAreas(EntityManagerInterface $em, PriceTier $obj) { // find the supported areas set with the price tier $areas = $em->getRepository(SupportedArea::class)->findBy(['price_tier' => $obj]); if (!empty($areas)) { // set the price tier id for the supported areas to null foreach ($areas as $area) { $area->setPriceTier(null); } $em->flush(); } } protected function updateSupportedAreas(EntityManagerInterface $em, PriceTier $obj, Request $req) { // get the selected areas $areas = $req->request->get('areas'); // check if no areas selected aka empty if (!empty($areas)) { foreach ($areas as $area_id) { // get supported area $supported_area = $em->getRepository(SupportedArea::class)->find($area_id); if ($supported_area != null) $supported_area->setPriceTier($obj); } } } protected function generateFormSets(EntityManagerInterface $em, PriceTier $pt = null) { // get the supported areas with no price tier id or price tier id is set to the one that is being updated $areas = $em->getRepository(SupportedArea::class)->findBy(['price_tier' => array(null, $pt)]); $areas_set = []; foreach ($areas as $area) { $areas_set[$area->getID()] = $area->getName(); } return [ 'areas' => $areas_set ]; } protected function setQueryFilters($datatable, QueryBuilder $query) { if (isset($datatable['query']['data-rows-search']) && !empty($datatable['query']['data-rows-search'])) { $query->where('q.name LIKE :filter') ->setParameter('filter', '%' . $datatable['query']['data-rows-search'] . '%'); } } }