diff --git a/composer.json b/composer.json index 562145d8..8516749e 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,7 @@ "ext-iconv": "*", "composer/package-versions-deprecated": "1.11.99.4", "data-dog/audit-bundle": "^0.1.10", + "doctrine/annotations": "^1.13", "doctrine/common": "^2", "doctrine/doctrine-bundle": "^2", "doctrine/doctrine-migrations-bundle": "^2", diff --git a/composer.lock b/composer.lock index 91636cc2..5914c598 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "653f8558c75614dd65421cb3eb48c29b", + "content-hash": "da765755121aaeb5c5a43aa74d7eeb76", "packages": [ { "name": "composer/package-versions-deprecated", @@ -4400,22 +4400,25 @@ }, { "name": "symfony/flex", - "version": "v1.17.3", + "version": "v1.21.8", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "acd0b5018fe9c2f5be6c67367987b5c723c0e096" + "reference": "bda5f869ac51c8e985a6fe9f964c4cb78228a369" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/acd0b5018fe9c2f5be6c67367987b5c723c0e096", - "reference": "acd0b5018fe9c2f5be6c67367987b5c723c0e096", + "url": "https://api.github.com/repos/symfony/flex/zipball/bda5f869ac51c8e985a6fe9f964c4cb78228a369", + "reference": "bda5f869ac51c8e985a6fe9f964c4cb78228a369", "shasum": "" }, "require": { "composer-plugin-api": "^1.0|^2.0", "php": ">=7.1" }, + "conflict": { + "composer/semver": "<1.7.2" + }, "require-dev": { "composer/composer": "^1.0.2|^2.0", "symfony/dotenv": "^4.4|^5.0|^6.0", @@ -4445,7 +4448,7 @@ "description": "Composer plugin for Symfony", "support": { "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v1.17.3" + "source": "https://github.com/symfony/flex/tree/v1.21.8" }, "funding": [ { @@ -4461,7 +4464,7 @@ "type": "tidelift" } ], - "time": "2021-11-22T18:48:50+00:00" + "time": "2024-10-07T08:51:39+00:00" }, { "name": "symfony/framework-bundle", @@ -7969,5 +7972,5 @@ "ext-iconv": "*" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/config/packages/catalyst_auth.yaml b/config/packages/catalyst_auth.yaml index b02b1fc9..e5f8e972 100644 --- a/config/packages/catalyst_auth.yaml +++ b/config/packages/catalyst_auth.yaml @@ -672,6 +672,22 @@ catalyst_auth: acls: - id: item_pricing.update label: Update + + - id: test_list + label: TestTypes + acls: + - id: test.menu + label: Menu + - id: test.add + label: Add + - id: test.update + label: Update + - id: test.delete + label: Delete + - id: test.list + label: List + + api: user_entity: "App\\Entity\\ApiUser" diff --git a/config/packages/catalyst_menu.yaml b/config/packages/catalyst_menu.yaml index 7972a414..12b98965 100644 --- a/config/packages/catalyst_menu.yaml +++ b/config/packages/catalyst_menu.yaml @@ -306,3 +306,7 @@ catalyst_menu: acl: item_pricing.update label: Item Pricing parent: item + + - id: test_list + acl: test.menu + label: TestTypes diff --git a/config/routes.yaml b/config/routes.yaml index e3cc0585..e69de29b 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -1,5 +0,0 @@ -#index: -# path: / -# controller: App\Controller\DefaultController::index -# -# diff --git a/config/routes/test.yaml b/config/routes/test.yaml new file mode 100644 index 00000000..5c9e4288 --- /dev/null +++ b/config/routes/test.yaml @@ -0,0 +1,34 @@ +test_list: + path: /test + controller: App\Controller\EntityController::index + methods: [GET] + +test_type_rows: + path: /test/rowdata + controller: App\Controller\EntityController::datatableRows + methods: [POST] + +test_type_add_form: + path: /test/newform + controller: App\Controller\EntityController::addForm + methods: [GET] + +test_type_add_submit: + path: /test + controller: App\Controller\EntityController::addSubmit + methods: [POST] + +test_type_update_form: + path: /test/{id} + controller: App\Controller\EntityController::updateForm + methods: [GET] + +test_type_update_submit: + path: /test/{id} + controller: App\Controller\EntityController::updateSubmit + methods: [POST] + +test_type_delete: + path: /test/{id} + controller: App\Controller\EntityController::deleteSubmit + methods: [DELETE] diff --git a/description b/description new file mode 100644 index 00000000..e69de29b diff --git a/id b/id new file mode 100644 index 00000000..e69de29b diff --git a/item b/item new file mode 100644 index 00000000..e69de29b diff --git a/price b/price new file mode 100644 index 00000000..e69de29b diff --git a/src/Controller/EntityController.php b/src/Controller/EntityController.php new file mode 100644 index 00000000..759848bc --- /dev/null +++ b/src/Controller/EntityController.php @@ -0,0 +1,256 @@ +render('entity/list.html.twig'); + } + + /** + * @Menu(selected="test_list") + * @IsGranted("test.add") + */ + public function addForm() + { + $test = new Test(); + $params = [ + 'obj' => $test, + 'mode' => 'create', + ]; + + // response + return $this->render('entity/form.html.twig', $params); + } + + /** + * @IsGranted("test.add") + */ + public function addSubmit(Request $req, EntityManagerInterface $em, ValidatorInterface $validator) + { + $test = new Test(); + + $this->setObject($test, $req); + + // validate + $errors = $validator->validate($test); + + // initialize error list + $error_array = []; + + // 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($test); + $em->flush(); + + // return successful response + return $this->json([ + 'success' => 'Changes have been saved!' + ]); + } + + + /** + * @Menu(selected="test_list") + * @IsGranted("test.update") + */ + public function updateForm($id, EntityManagerInterface $em, Test $test) + { + $params = []; + $params['obj'] = $test; + $params['mode'] = 'update'; + + // response + return $this->render('entity/form.html.twig', $params); + } + + /** + * @IsGranted("test.update") + */ + public function updateSubmit(Request $req, EntityManagerInterface $em, ValidatorInterface $validator, Test $test) + { + $this->setObject($test, $req); + + // validate + $errors = $validator->validate($test); + + // initialize error list + $error_array = []; + + // 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->flush(); + + // return successful response + return $this->json([ + 'success' => 'Changes have been saved!' + ]); + } + + /** + * @IsGranted("test.delete") + */ + public function deleteSubmit(EntityManagerInterface $em, Test $test) + { + // delete this object + $em->remove($test); + $em->flush(); + + // response + $response = new Response(); + $response->setStatusCode(Response::HTTP_OK); + $response->send(); + } + + protected function setObject(Test $obj, Request $req) + { + // set and save values + $obj->setItem($req->request->get('item')) + ->setPrice($req->request->get('price')) + ->setDescription($req->request->get('description')); + + } + + 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'] . '%'); + } + } + + /** + * @IsGranted("test.list") + */ + public function datatableRows(Request $req) + { + // get query builder + $qb = $this->getDoctrine() + ->getRepository(Test::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['item'] = $orow->getItem(); + $row['price'] = $orow->getPrice(); + $row['description'] = $orow->getDescription(); + + + // add row metadata + $row['meta'] = [ + 'update_url' => '', + 'delete_url' => '' + ]; + + // add crud urls + if ($this->isGranted('test.update')) + $row['meta']['update_url'] = $this->generateUrl('test_type_update_form', ['id' => $row['id']]); + if ($this->isGranted('test.delete')) + $row['meta']['delete_url'] = $this->generateUrl('test_type_delete', ['id' => $row['id']]); + + $rows[] = $row; + } + + // response + return $this->json([ + 'meta' => $meta, + 'data' => $rows + ]); + +} + +} diff --git a/src/Entity/Test.php b/src/Entity/Test.php new file mode 100644 index 00000000..960174b7 --- /dev/null +++ b/src/Entity/Test.php @@ -0,0 +1,75 @@ +id; + } + + public function getItem(): ?string + { + return $this->item; + } + + public function setItem(string $item): self + { + $this->item = $item; + + return $this; + } + + public function getPrice(): ?string + { + return $this->price; + } + + public function setPrice(string $price): self + { + $this->price = $price; + + return $this; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function setDescription(string $description): self + { + $this->description = $description; + + return $this; + } +} diff --git a/src/Migrations/Version20241017062927.php b/src/Migrations/Version20241017062927.php new file mode 100644 index 00000000..e6822d49 --- /dev/null +++ b/src/Migrations/Version20241017062927.php @@ -0,0 +1,39 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('CREATE TABLE test (id INT AUTO_INCREMENT NOT NULL, placeholder VARCHAR(120) NOT NULL, password LONGTEXT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE battery CHANGE date_update date_update timestamp default current_timestamp on update current_timestamp'); + $this->addSql('ALTER TABLE sap_battery CHANGE date_update date_update timestamp default current_timestamp on update current_timestamp'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('DROP TABLE test'); + $this->addSql('ALTER TABLE battery CHANGE date_update date_update DATETIME DEFAULT CURRENT_TIMESTAMP'); + $this->addSql('ALTER TABLE sap_battery CHANGE date_update date_update DATETIME DEFAULT CURRENT_TIMESTAMP'); + } +} diff --git a/src/Migrations/Version20241018002028.php b/src/Migrations/Version20241018002028.php new file mode 100644 index 00000000..bf0616d5 --- /dev/null +++ b/src/Migrations/Version20241018002028.php @@ -0,0 +1,39 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE battery CHANGE date_update date_update timestamp default current_timestamp on update current_timestamp'); + $this->addSql('ALTER TABLE sap_battery CHANGE date_update date_update timestamp default current_timestamp on update current_timestamp'); + $this->addSql('ALTER TABLE test ADD item VARCHAR(255) NOT NULL, ADD price NUMERIC(10, 2) NOT NULL, DROP placeholder, CHANGE password description LONGTEXT NOT NULL'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE battery CHANGE date_update date_update DATETIME DEFAULT CURRENT_TIMESTAMP'); + $this->addSql('ALTER TABLE sap_battery CHANGE date_update date_update DATETIME DEFAULT CURRENT_TIMESTAMP'); + $this->addSql('ALTER TABLE test ADD placeholder VARCHAR(120) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, DROP item, DROP price, CHANGE description password LONGTEXT CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`'); + } +} diff --git a/src/Migrations/Version20241018012501.php b/src/Migrations/Version20241018012501.php new file mode 100644 index 00000000..5a638573 --- /dev/null +++ b/src/Migrations/Version20241018012501.php @@ -0,0 +1,39 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('CREATE TABLE test (id INT AUTO_INCREMENT NOT NULL, item VARCHAR(255) NOT NULL, price NUMERIC(8, 2) NOT NULL, description LONGTEXT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE battery CHANGE date_update date_update timestamp default current_timestamp on update current_timestamp'); + $this->addSql('ALTER TABLE sap_battery CHANGE date_update date_update timestamp default current_timestamp on update current_timestamp'); + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('DROP TABLE test'); + $this->addSql('ALTER TABLE battery CHANGE date_update date_update DATETIME DEFAULT CURRENT_TIMESTAMP'); + $this->addSql('ALTER TABLE sap_battery CHANGE date_update date_update DATETIME DEFAULT CURRENT_TIMESTAMP'); + } +} diff --git a/src/Repository/TestRepository.php b/src/Repository/TestRepository.php new file mode 100644 index 00000000..f2ff134a --- /dev/null +++ b/src/Repository/TestRepository.php @@ -0,0 +1,50 @@ +createQueryBuilder('t') + ->andWhere('t.exampleField = :val') + ->setParameter('val', $value) + ->orderBy('t.id', 'ASC') + ->setMaxResults(10) + ->getQuery() + ->getResult() + ; + } + */ + + /* + public function findOneBySomeField($value): ?Test + { + return $this->createQueryBuilder('t') + ->andWhere('t.exampleField = :val') + ->setParameter('val', $value) + ->getQuery() + ->getOneOrNullResult() + ; + } + */ +} diff --git a/templates/entity/form.html.twig b/templates/entity/form.html.twig new file mode 100644 index 00000000..784a7413 --- /dev/null +++ b/templates/entity/form.html.twig @@ -0,0 +1,151 @@ +{% extends 'base.html.twig' %} + +{% block body %} + +