diff --git a/src/Controller/AttachmentTypeController.php b/src/Controller/AttachmentTypeController.php index 58719aa1..cc9e1687 100644 --- a/src/Controller/AttachmentTypeController.php +++ b/src/Controller/AttachmentTypeController.php @@ -33,11 +33,16 @@ namespace App\Controller; use App\Entity\AttachmentType; +use App\Entity\StructuralDBElement; use App\Form\BaseEntityAdminForm; +use App\Form\ExportType; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\ResponseHeaderBag; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Serializer\SerializerInterface; /** * @Route("/attachment_type") @@ -119,4 +124,91 @@ class AttachmentTypeController extends AbstractController return $this->redirectToRoute('attachment_type_new'); } + + /** + * @Route("/export") + * @param Request $request + * @param SerializerInterface $serializer + * @param EntityManagerInterface $em + * @return Response + */ + public function exportAll(Request $request, SerializerInterface $serializer, EntityManagerInterface $em) + { + $entities = $em->getRepository(AttachmentType::class)->findAll(); + + return $this->exportHelper($entities, $request, $serializer); + } + + /** + * @Route("/{id}/export", name="attachment_type_export") + * @param Request $request + * @param AttachmentType $entity + */ + public function exportEntity(Request $request, AttachmentType $entity, SerializerInterface $serializer) + { + return $this->exportHelper($entity, $request, $serializer); + } + + protected function exportHelper($entity, Request $request, SerializerInterface $serializer) : Response + { + $format = $request->get('format') ?? "json"; + + //Check if we have one of the supported formats + if (!in_array($format, ['json', 'csv', 'yaml', 'xml'])) { + throw new \InvalidArgumentException("Given format is not supported!"); + } + + //Check export verbosity level + $level = $request->get('level') ?? 'extended'; + if (!in_array($level, ['simple', 'extended', 'full'])) { + throw new \InvalidArgumentException('Given level is not supported!'); + } + + //Check for include children option + $include_children = $request->get('include_children') ?? false; + + //Check which groups we need to export, based on level and include_children + $groups = array($level); + if ($include_children) { + $groups[] = 'include_children'; + } + + //Plain text should work for all types + $content_type = "text/plain"; + + //Try to use better content types based on the format + switch ($format) { + case 'xml': + $content_type = "application/xml"; + break; + case 'json': + $content_type = "application/json"; + break; + } + + $response = new Response($serializer->serialize($entity, $format, + [ + 'groups' => $groups, + 'as_collection' => true, + 'csv_delimiter' => ';', //Better for Excel + 'xml_root_node_name' => 'PartDBExport' + ])); + + $response->headers->set('Content-Type', $content_type); + + //If view option is not specified, then download the file. + if (!$request->get('view')) { + $filename = "export_" . $entity->getName() . "_" . $level . "." . $format; + + // Create the disposition of the file + $disposition = $response->headers->makeDisposition( + ResponseHeaderBag::DISPOSITION_ATTACHMENT, + $filename + ); + // Set the content disposition + $response->headers->set('Content-Disposition', $disposition); + } + + return $response; + } } \ No newline at end of file diff --git a/src/Entity/AttachmentType.php b/src/Entity/AttachmentType.php index fb26f467..9f3a3f0f 100644 --- a/src/Entity/AttachmentType.php +++ b/src/Entity/AttachmentType.php @@ -77,7 +77,6 @@ class AttachmentType extends StructuralDBElement */ public function getIDString(): string { - return ''; - //return 'AT' . sprintf('%09d', $this->getID()); + return 'AT' . sprintf('%09d', $this->getID()); } } diff --git a/src/Entity/DBElement.php b/src/Entity/DBElement.php index 32cd3cfa..0699e000 100644 --- a/src/Entity/DBElement.php +++ b/src/Entity/DBElement.php @@ -24,6 +24,8 @@ declare(strict_types=1); namespace App\Entity; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation\DiscriminatorMap; +use Symfony\Component\Serializer\Annotation\Groups; /** * This class is for managing all database objects. @@ -36,6 +38,23 @@ use Doctrine\ORM\Mapping as ORM; * @ORM\MappedSuperclass() * * @ORM\EntityListeners({"App\Security\EntityListeners\ElementPermissionListener"}) + * + * @DiscriminatorMap(typeProperty="type", mapping={ + * "attachment_type" = "App\Entity\AttachmentType", + * "attachment" = "App\Entity\Attachment", + * "category" = "App\Entity\Attachment", + * "device" = "App\Entity\Device", + * "device_part" = "App\Entity\DevicePart", + * "footprint" = "App\Entity\Footprint", + * "group" = "App\Entity\Group", + * "manufacturer" = "App\Entity\Manufacturer", + * "orderdetail" = "App\Entity\Orderdetail", + * "part" = "App\Entity\Part", + * "pricedetail" = "App\Entity\Pricedetail", + * "storelocation" = "App\Entity\Storelocation", + * "supplier" = "App\Entity\Supplier", + * "user" = "App\Entity\User" + * }) */ abstract class DBElement { @@ -43,6 +62,7 @@ abstract class DBElement * @ORM\Column(type="integer") * @ORM\Id() * @ORM\GeneratedValue() + * @Groups({"full"}) */ protected $id; @@ -64,6 +84,7 @@ abstract class DBElement * This should have a form like P000014, for a part with ID 14. * * @return string The ID as a string; + * */ abstract public function getIDString(): string; diff --git a/src/Entity/NamedDBElement.php b/src/Entity/NamedDBElement.php index da6dd995..d063e9f5 100644 --- a/src/Entity/NamedDBElement.php +++ b/src/Entity/NamedDBElement.php @@ -25,6 +25,7 @@ namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Serializer\Annotation\Groups; /** * All subclasses of this class have an attribute "name". @@ -38,18 +39,21 @@ abstract class NamedDBElement extends DBElement * @var string The name of this element. * @ORM\Column(type="string") * @Assert\NotBlank() + * @Groups({"simple", "extended", "full"}) */ protected $name = ''; /** * @var \DateTime The date when this element was modified the last time. * @ORM\Column(type="datetimetz", name="last_modified") + * @Groups({"extended", "full"}) */ protected $lastModified; /** * @var \DateTime The date when this element was created. * @ORM\Column(type="datetimetz", name="datetime_added") + * @Groups({"extended", "full"}) */ protected $addedDate; diff --git a/src/Entity/StructuralDBElement.php b/src/Entity/StructuralDBElement.php index d3e9e0c1..ae40a8d5 100644 --- a/src/Entity/StructuralDBElement.php +++ b/src/Entity/StructuralDBElement.php @@ -27,6 +27,8 @@ use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\PersistentCollection; use App\Validator\Constraints\NoneOfItsChildren; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; +use Symfony\Component\Serializer\Annotation\DiscriminatorMap; +use Symfony\Component\Serializer\Annotation\Groups; /** * All elements with the fields "id", "name" and "parent_id" (at least). @@ -52,17 +54,20 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement // subclasses /** * @var StructuralDBElement[] + * @Groups({"include_children"}) */ protected $children; /** * @var StructuralDBElement * @NoneOfItsChildren() + * @Groups({"include_parents"}) */ protected $parent; /** * @var string The comment info for this element * @ORM\Column(type="string", nullable=true) + * @Groups({"simple", "extended", "full"}) */ protected $comment; @@ -78,7 +83,9 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement protected $level = 0; /** @var string[] all names of all parent elements as a array of strings, - * the last array element is the name of the element itself */ + * the last array element is the name of the element itself + * + */ private $full_path_strings; /****************************************************************************** @@ -154,24 +161,25 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement /** * Get the level. * - * The level of the root node is -1. + * The level of the root node is -1. * * @return int the level of this element (zero means a most top element * [a subelement of the root node]) + * */ public function getLevel(): int { - if (0 === $this->level) { + /** + * Only check for nodes that have a parent. In the other cases zero is correct. + */ + if (0 === $this->level && $this->parent !== null) { $element = $this->parent; - $parent_id = $element->getParentID(); - while ($parent_id > 0) { + while ($element !== null) { /** @var StructuralDBElement $element */ $element = $element->parent; - $parent_id = $element->getParentID(); ++$this->level; } } - return $this->level; } @@ -181,6 +189,7 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement * @param string $delimeter the delimeter of the returned string * * @return string the full path (incl. the name of this element), delimeted by $delimeter + * */ public function getFullPath(string $delimeter = self::PATH_DELIMITER_ARROW): string { @@ -216,6 +225,11 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement return $this->children; } + public function getChildren(): PersistentCollection + { + return $this->children; + } + /****************************************************************************** * * Setters diff --git a/templates/AdminPages/EntityAdminBase.html.twig b/templates/AdminPages/EntityAdminBase.html.twig index b76a48eb..6dcd92bf 100644 --- a/templates/AdminPages/EntityAdminBase.html.twig +++ b/templates/AdminPages/EntityAdminBase.html.twig @@ -29,8 +29,6 @@
- {{ form_start(form) }} -
{% if entity.ID %} @@ -43,14 +41,26 @@
+ {{ form_start(form) }} {{ form_row(form.name) }} {{ form_row(form.parent) }} {% block additional_controls %}{% endblock %} {{ form_row(form.comment) }} + {{ form_row(form.save) }} + {{ form_row(form.reset) }} + {{ form_end(form) }} + + {# Only include on existing parts #} + {% if entity.id %} + {{ include('AdminPages/_delete_form.html.twig') }} + {% endif %}
@@ -87,20 +97,59 @@
+ + {% if entity.id %} +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
+
+
+ {% endif %} - {{ form_row(form.save) }} - {{ form_row(form.reset) }} + - - {{ form_end(form) }} - - {# Only include on existing parts #} - {% if entity.id %} - {{ include('AdminPages/_delete_form.html.twig') }} - {% endif %}