| @@ -2317,28 +2317,26 @@ components: | |||
| description: '' | |||
| deprecated: false | |||
| properties: | |||
| dbId: | |||
| id: | |||
| readOnly: true | |||
| type: | |||
| - integer | |||
| - 'null' | |||
| contentUrl: | |||
| externalDocs: | |||
| url: 'https://schema.org/contentUrl' | |||
| type: integer | |||
| file: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| format: binary | |||
| filePath: | |||
| readOnly: true | |||
| type: | |||
| - string | |||
| - 'null' | |||
| createdBy: | |||
| $ref: '#/components/schemas/User' | |||
| createdAt: | |||
| readOnly: true | |||
| type: | |||
| - string | |||
| - 'null' | |||
| type: string | |||
| format: date-time | |||
| required: | |||
| - file | |||
| MediaObject.jsonld: | |||
| type: object | |||
| description: '' | |||
| @@ -2676,11 +2674,11 @@ components: | |||
| lastName: | |||
| type: string | |||
| image: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| anyOf: | |||
| - | |||
| $ref: '#/components/schemas/MediaObject' | |||
| - | |||
| type: 'null' | |||
| imageUrl: | |||
| readOnly: true | |||
| type: | |||
| @@ -2758,11 +2756,11 @@ components: | |||
| lastName: | |||
| type: string | |||
| image: | |||
| type: | |||
| - string | |||
| - 'null' | |||
| format: iri-reference | |||
| example: 'https://example.com/' | |||
| anyOf: | |||
| - | |||
| $ref: '#/components/schemas/MediaObject.jsonld' | |||
| - | |||
| type: 'null' | |||
| imageUrl: | |||
| readOnly: true | |||
| type: | |||
| @@ -2836,6 +2834,7 @@ components: | |||
| required: | |||
| - trip | |||
| - user | |||
| - completed | |||
| UserTrip.jsonld: | |||
| type: object | |||
| description: '' | |||
| @@ -2900,6 +2899,7 @@ components: | |||
| required: | |||
| - trip | |||
| - user | |||
| - completed | |||
| UserTripEvent: | |||
| type: object | |||
| description: '' | |||
| @@ -32,9 +32,10 @@ export const locationJsonldForm = new FormGroup({ | |||
| }); | |||
| export const mediaObjectForm = new FormGroup({ | |||
| dbId: new FormControl(null, []), | |||
| contentUrl: new FormControl(null, []), | |||
| id: new FormControl(null, []), | |||
| file: new FormControl(null, [Validators.required]), | |||
| filePath: new FormControl(null, []), | |||
| createdBy: new FormControl(null, []), | |||
| createdAt: new FormControl(null, []) | |||
| }); | |||
| @@ -140,7 +141,7 @@ export const userTripForm = new FormGroup({ | |||
| trip: new FormControl(null, [Validators.required]), | |||
| user: new FormControl(null, [Validators.required]), | |||
| captainName: new FormControl(null, []), | |||
| completed: new FormControl(null, []), | |||
| completed: new FormControl(null, [Validators.required]), | |||
| signature: new FormControl(null, []), | |||
| signatureUrl: new FormControl(null, []), | |||
| completedDate: new FormControl(null, []), | |||
| @@ -152,7 +153,7 @@ export const userTripJsonldForm = new FormGroup({ | |||
| trip: new FormControl(null, [Validators.required]), | |||
| user: new FormControl(null, [Validators.required]), | |||
| captainName: new FormControl(null, []), | |||
| completed: new FormControl(null, []), | |||
| completed: new FormControl(null, [Validators.required]), | |||
| signature: new FormControl(null, []), | |||
| signatureUrl: new FormControl(null, []), | |||
| completedDate: new FormControl(null, []), | |||
| @@ -1,41 +1,43 @@ | |||
| <div class="spt-container"> | |||
| <div class="spt-form"> | |||
| <form [formGroup]="userTripForm" (ngSubmit)="onSubmit()"> | |||
| @if (data !== undefined) { | |||
| <form [formGroup]="userTripForm" (ngSubmit)="onSubmit()"> | |||
| <input type="hidden" formControlName="trip" /> | |||
| <input type="hidden" formControlName="user" /> | |||
| <input type="hidden" formControlName="signature" /> | |||
| <div class="mb-3"> | |||
| <label for="captainName" class="form-label">{{ 'trip.captain_name' | translate }}:</label> | |||
| <input type="text" class="form-control" id="captainName" formControlName="captainName"/> | |||
| </div> | |||
| <div class="col-12 col-sm-6 col-md-4 col-lg-3 mb-3 switch-widget"> | |||
| <p class="form-label">{{ 'user_trip.completed' | translate }}:</p> | |||
| <label class="switch"> | |||
| <input type="checkbox" formControlName="completed" [disabled]="data ? data.completed : false"> | |||
| <span class="slider round"></span> | |||
| </label> | |||
| </div> | |||
| <input type="hidden" formControlName="trip" /> | |||
| <input type="hidden" formControlName="user" /> | |||
| <input type="hidden" formControlName="signature" /> | |||
| <div class="mb-3"> | |||
| <label for="captainName" class="form-label">{{ 'trip.captain_name' | translate }}:</label> | |||
| <input type="text" class="form-control" id="captainName" formControlName="captainName"/> | |||
| </div> | |||
| <div class="col-12 col-sm-6 col-md-4 col-lg-3 mb-3 switch-widget"> | |||
| <p class="form-label">{{ 'user_trip.completed' | translate }}:</p> | |||
| <label class="switch"> | |||
| <input type="checkbox" formControlName="completed" [disabled]="data.completed"> | |||
| <span class="slider round"></span> | |||
| </label> | |||
| </div> | |||
| <!-- Neues File-Upload-Feld für MediaObject --> | |||
| <div class="mb-3"> | |||
| <label for="mediaFile" class="form-label">{{ 'user_trip.signature' | translate }}:</label> | |||
| <input type="file" class="form-control" id="mediaFile" (change)="onFileSelected($event)"/> | |||
| @if (selectedFile) { | |||
| <small class="text-muted">{{ selectedFile.name }}</small> | |||
| } | |||
| @if (data.signatureUrl) { | |||
| <div class="mt-1"> | |||
| <img [src]="data.signatureUrl" alt="Signatur" class="img-fluid" /> | |||
| </div> | |||
| } | |||
| </div> | |||
| </form> | |||
| } | |||
| <!-- Neues File-Upload-Feld für MediaObject --> | |||
| <div class="mb-3"> | |||
| <label for="mediaFile" class="form-label">{{ 'user_trip.signature' | translate }}:</label> | |||
| <input type="file" class="form-control" id="mediaFile" (change)="onFileSelected($event)"/> | |||
| @if (selectedFile) { | |||
| <small class="text-muted">{{ selectedFile.name }}</small> | |||
| } | |||
| @if (data?.signature?.contentUrl) { | |||
| <div class="mt-2"> | |||
| <small>{{ 'user_trip.current_file' | translate }}: {{ getFileNameFromUrl(data?.signature?.contentUrl) }}</small> | |||
| </div> | |||
| } | |||
| </div> | |||
| </form> | |||
| </div> | |||
| <div class="flex gap-2"> | |||
| <!-- <button type="submit" class="btn btn-primary" [disabled]="form.invalid" (click)="onSubmit()">--> | |||
| <button type="submit" class="btn btn-primary" (click)="onSubmit()"> | |||
| <button type="submit" class="btn btn-primary" [disabled]="form.invalid" (click)="onSubmit()"> | |||
| {{ 'basic.save' | translate }} | |||
| </button> | |||
| @@ -5,7 +5,7 @@ import { | |||
| FormSubmitEvent | |||
| } from "@app/_components/_abstract/abstract-data-form-component"; | |||
| import { | |||
| LocationService, MediaObjectJsonld, MediaObjectService, TripJsonld, | |||
| LocationService, MediaObjectJsonld, MediaObjectService, TripJsonld, UserTrip, | |||
| UserTripJsonld, | |||
| UserTripService, | |||
| VesselService | |||
| @@ -74,21 +74,8 @@ export class UserTripFormComponent extends AbstractDataFormComponent<UserTripJso | |||
| } | |||
| override onSubmit(): void { | |||
| if (!this.form.valid) { | |||
| console.log('Form is invalid:', this.form.errors); | |||
| Object.keys(this.form.controls).forEach(key => { | |||
| const control = this.form.get(key); | |||
| if (control?.invalid) { | |||
| console.log(`Control '${key}' is invalid:`, control.errors); | |||
| } | |||
| }); | |||
| return; | |||
| } | |||
| // Wenn keine Datei ausgewählt wurde, rufe direkt die Elternmethode auf | |||
| if (!this.selectedFile) { | |||
| // Wenn keine Datei ausgewählt wurde und keine vorhandene Signature existiert, | |||
| // setzen wir sie auf undefined (nicht null) | |||
| const currentValue = this.form.get('signature')?.value; | |||
| if (currentValue === null) { | |||
| this.form.patchValue({ | |||
| @@ -103,12 +90,11 @@ export class UserTripFormComponent extends AbstractDataFormComponent<UserTripJso | |||
| this.mediaObjectService.mediaObjectsPost(this.selectedFile).subscribe({ | |||
| next: (mediaObject) => { | |||
| // 2. Update the form data with the new mediaObject | |||
| console.log(mediaObject.id); | |||
| this.form.patchValue({ | |||
| signature: mediaObject | |||
| signature: mediaObject.id | |||
| }); | |||
| console.log('Form after file upload:', this.form.value); | |||
| // 3. Call the parent method to handle the standard save process | |||
| super.onSubmit(); | |||
| }, | |||
| @@ -49,7 +49,9 @@ model/tripJsonld.ts | |||
| model/tripLocation.ts | |||
| model/tripLocationJsonld.ts | |||
| model/user.ts | |||
| model/userImage.ts | |||
| model/userJsonld.ts | |||
| model/userJsonldImage.ts | |||
| model/userTrip.ts | |||
| model/userTripEvent.ts | |||
| model/userTripEventJsonld.ts | |||
| @@ -9,15 +9,17 @@ | |||
| * https://openapi-generator.tech | |||
| * Do not edit the class manually. | |||
| */ | |||
| import { User } from './user'; | |||
| /** | |||
| * | |||
| */ | |||
| export interface MediaObject { | |||
| readonly dbId?: number | null; | |||
| contentUrl?: string | null; | |||
| readonly filePath?: string | null; | |||
| readonly createdAt?: string | null; | |||
| readonly id?: number; | |||
| file: Blob | null; | |||
| filePath?: string | null; | |||
| createdBy?: User; | |||
| readonly createdAt?: string; | |||
| } | |||
| @@ -28,7 +28,9 @@ export * from './tripJsonld'; | |||
| export * from './tripLocation'; | |||
| export * from './tripLocationJsonld'; | |||
| export * from './user'; | |||
| export * from './userImage'; | |||
| export * from './userJsonld'; | |||
| export * from './userJsonldImage'; | |||
| export * from './userTrip'; | |||
| export * from './userTripEvent'; | |||
| export * from './userTripEventJsonld'; | |||
| @@ -9,6 +9,7 @@ | |||
| * https://openapi-generator.tech | |||
| * Do not edit the class manually. | |||
| */ | |||
| import { UserImage } from './userImage'; | |||
| /** | |||
| @@ -20,7 +21,7 @@ export interface User { | |||
| firstName: string; | |||
| referenceId: string; | |||
| lastName: string; | |||
| image?: string | null; | |||
| image?: UserImage; | |||
| readonly imageUrl?: string | null; | |||
| readonly fullName?: string | null; | |||
| /** | |||
| @@ -0,0 +1,23 @@ | |||
| /** | |||
| * Imaq Platform | |||
| * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) | |||
| * | |||
| * The version of the OpenAPI document: 1.0.0 | |||
| * | |||
| * | |||
| * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). | |||
| * https://openapi-generator.tech | |||
| * Do not edit the class manually. | |||
| */ | |||
| import { User } from './user'; | |||
| import { MediaObject } from './mediaObject'; | |||
| export interface UserImage { | |||
| readonly id?: any | null; | |||
| file: any | null; | |||
| filePath?: any | null; | |||
| createdBy?: User; | |||
| readonly createdAt?: any | null; | |||
| } | |||
| @@ -9,6 +9,7 @@ | |||
| * https://openapi-generator.tech | |||
| * Do not edit the class manually. | |||
| */ | |||
| import { UserJsonldImage } from './userJsonldImage'; | |||
| import { EventJsonldContext } from './eventJsonldContext'; | |||
| @@ -24,7 +25,7 @@ export interface UserJsonld { | |||
| firstName: string; | |||
| referenceId: string; | |||
| lastName: string; | |||
| image?: string | null; | |||
| image?: UserJsonldImage; | |||
| readonly imageUrl?: string | null; | |||
| readonly fullName?: string | null; | |||
| /** | |||
| @@ -0,0 +1,25 @@ | |||
| /** | |||
| * Imaq Platform | |||
| * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) | |||
| * | |||
| * The version of the OpenAPI document: 1.0.0 | |||
| * | |||
| * | |||
| * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). | |||
| * https://openapi-generator.tech | |||
| * Do not edit the class manually. | |||
| */ | |||
| import { MediaObjectJsonld } from './mediaObjectJsonld'; | |||
| import { EventJsonldContext } from './eventJsonldContext'; | |||
| export interface UserJsonldImage { | |||
| context?: EventJsonldContext; | |||
| readonly id?: any | null; | |||
| readonly type?: any | null; | |||
| readonly dbId?: any | null; | |||
| contentUrl?: any | null; | |||
| readonly filePath?: any | null; | |||
| readonly createdAt?: any | null; | |||
| } | |||
| @@ -22,7 +22,7 @@ export interface UserTrip { | |||
| trip: Trip; | |||
| user: User; | |||
| captainName?: string | null; | |||
| completed?: boolean; | |||
| completed: boolean; | |||
| signature?: MediaObject; | |||
| readonly signatureUrl?: string | null; | |||
| completedDate?: string | null; | |||
| @@ -26,7 +26,7 @@ export interface UserTripJsonld { | |||
| trip: TripJsonld; | |||
| user: UserJsonld; | |||
| captainName?: string | null; | |||
| completed?: boolean; | |||
| completed: boolean; | |||
| signature?: MediaObjectJsonld; | |||
| readonly signatureUrl?: string | null; | |||
| completedDate?: string | null; | |||
| @@ -57,20 +57,20 @@ class TripApi | |||
| #[ApiProperty(writable: false)] | |||
| public ?int $dbId = null; | |||
| /** | |||
| * @var VesselApi | |||
| */ | |||
| #[ApiProperty( | |||
| writable: true, | |||
| readableLink: true, | |||
| writableLink: true, | |||
| builtinTypes: [ | |||
| new Type( | |||
| 'object', | |||
| class: VesselApi::class, | |||
| ) | |||
| ] | |||
| )] | |||
| // /** | |||
| // * @var VesselApi | |||
| // */ | |||
| // #[ApiProperty( | |||
| // writable: true, | |||
| // readableLink: true, | |||
| // writableLink: false, | |||
| // builtinTypes: [ | |||
| // new Type( | |||
| // 'object', | |||
| // class: VesselApi::class, | |||
| // ) | |||
| // ] | |||
| // )] | |||
| public ?VesselApi $vessel = null; | |||
| #[ApiProperty(writable: false)] | |||
| @@ -80,36 +80,36 @@ class TripApi | |||
| public ?string $captainName = null; | |||
| /** | |||
| * @var LocationApi | |||
| */ | |||
| #[ApiProperty( | |||
| writable: true, | |||
| readableLink: true, | |||
| writableLink: true, | |||
| builtinTypes: [ | |||
| new Type( | |||
| 'object', | |||
| class: LocationApi::class, | |||
| ) | |||
| ] | |||
| )] | |||
| // /** | |||
| // * @var LocationApi | |||
| // */ | |||
| // #[ApiProperty( | |||
| // writable: true, | |||
| // readableLink: true, | |||
| // writableLink: false, | |||
| // builtinTypes: [ | |||
| // new Type( | |||
| // 'object', | |||
| // class: LocationApi::class, | |||
| // ) | |||
| // ] | |||
| // )] | |||
| public ?LocationApi $startLocation = null; | |||
| /** | |||
| * @var LocationApi | |||
| */ | |||
| #[ApiProperty( | |||
| writable: true, | |||
| readableLink: true, | |||
| writableLink: true, | |||
| builtinTypes: [ | |||
| new Type( | |||
| 'object', | |||
| class: LocationApi::class, | |||
| ) | |||
| ] | |||
| )] | |||
| // /** | |||
| // * @var LocationApi | |||
| // */ | |||
| // #[ApiProperty( | |||
| // writable: true, | |||
| // readableLink: true, | |||
| // writableLink: false, | |||
| // builtinTypes: [ | |||
| // new Type( | |||
| // 'object', | |||
| // class: LocationApi::class, | |||
| // ) | |||
| // ] | |||
| // )] | |||
| public ?LocationApi $endLocation = null; | |||
| #[Assert\NotBlank] | |||
| @@ -95,6 +95,7 @@ class UserTripApi | |||
| public ?string $captainName = null; | |||
| #[Assert\NotNull] | |||
| public bool $completed = false; | |||
| /** | |||
| @@ -22,7 +22,6 @@ final class CreateMediaObjectAction extends AbstractController | |||
| public function __construct( | |||
| private MicroMapperInterface $microMapper, | |||
| private EntityManagerInterface $em, | |||
| private SerializerInterface $serializer, | |||
| private NormalizerInterface $normalizer | |||
| ) { | |||
| } | |||
| @@ -1,67 +1,20 @@ | |||
| <?php | |||
| /** | |||
| * @author Daniel Knudsen <d.knudsen@spawntree.de> | |||
| * @date 25.01.24 | |||
| */ | |||
| namespace App\Entity; | |||
| use ApiPlatform\Metadata\ApiProperty; | |||
| use ApiPlatform\Metadata\ApiResource; | |||
| use ApiPlatform\Metadata\Delete; | |||
| use ApiPlatform\Metadata\Get; | |||
| use ApiPlatform\Metadata\GetCollection; | |||
| use ApiPlatform\Metadata\Post; | |||
| use ApiPlatform\OpenApi\Model; | |||
| use App\Controller\CreateMediaObjectAction; | |||
| use App\Repository\MediaObjectRepository; | |||
| use Doctrine\ORM\Mapping as ORM; | |||
| use Symfony\Component\HttpFoundation\File\File; | |||
| use Symfony\Component\Serializer\Annotation\Groups; | |||
| use Symfony\Component\Validator\Constraints as Assert; | |||
| use Vich\UploaderBundle\Mapping\Annotation as Vich; | |||
| #[Vich\Uploadable] | |||
| #[ORM\Entity] | |||
| #[ApiResource( | |||
| shortName: 'MediaObject', | |||
| types: ['https://schema.org/MediaObject'], | |||
| operations: [ | |||
| new Get(), | |||
| new GetCollection(), | |||
| new Post( | |||
| controller: CreateMediaObjectAction::class, | |||
| openapi: new Model\Operation( | |||
| requestBody: new Model\RequestBody( | |||
| content: new \ArrayObject([ | |||
| 'multipart/form-data' => [ | |||
| 'schema' => [ | |||
| 'type' => 'object', | |||
| 'properties' => [ | |||
| 'file' => [ | |||
| 'type' => 'string', | |||
| 'format' => 'binary' | |||
| ] | |||
| ] | |||
| ] | |||
| ] | |||
| ]) | |||
| ) | |||
| ), | |||
| deserialize: false | |||
| ), | |||
| new Delete(), | |||
| ], | |||
| security: 'is_granted("ROLE_USER")', | |||
| )] | |||
| #[ORM\Entity(repositoryClass: MediaObjectRepository::class)] | |||
| class MediaObject | |||
| { | |||
| #[ORM\Id, ORM\Column, ORM\GeneratedValue] | |||
| private ?int $id = null; | |||
| #[ApiProperty(types: ['https://schema.org/contentUrl'])] | |||
| public ?string $contentUrl = null; | |||
| #[Vich\UploadableField(mapping: 'media_object', fileNameProperty: 'filePath')] | |||
| #[Assert\NotNull()] | |||
| public ?File $file = null; | |||
| @@ -87,11 +40,6 @@ class MediaObject | |||
| return $this->id; | |||
| } | |||
| public function getContentUrl(): ?string | |||
| { | |||
| return $this->contentUrl; | |||
| } | |||
| public function getFile(): ?File | |||
| { | |||
| return $this->file; | |||
| @@ -111,5 +59,4 @@ class MediaObject | |||
| { | |||
| return $this->createdAt; | |||
| } | |||
| } | |||
| @@ -0,0 +1,44 @@ | |||
| <?php | |||
| namespace App\Mapper; | |||
| use App\ApiResource\MediaObjectApi; | |||
| use App\Entity\MediaObject; | |||
| use App\Repository\MediaObjectRepository; | |||
| use Symfonycasts\MicroMapper\AsMapper; | |||
| use Symfonycasts\MicroMapper\MapperInterface; | |||
| #[AsMapper(from: MediaObjectApi::class, to: MediaObject::class)] | |||
| class MediaObjectApiToEntityMapper implements MapperInterface | |||
| { | |||
| public function __construct( | |||
| private MediaObjectRepository $repository | |||
| ) { | |||
| } | |||
| public function load(object $from, string $toClass, array $context): object | |||
| { | |||
| $dto = $from; | |||
| assert($dto instanceof MediaObjectApi); | |||
| // Wenn eine ID vorhanden ist, lade das vorhandene Entity | |||
| if ($dto->id) { | |||
| $entity = $this->repository->find($dto->id); | |||
| if (!$entity) { | |||
| throw new \Exception('MediaObject not found with ID: ' . $dto->id); | |||
| } | |||
| return $entity; | |||
| } | |||
| // Da neue MediaObjects nur über den Controller erstellt werden, | |||
| // werfen wir hier eine Exception, wenn kein existierendes MediaObject gefunden wurde | |||
| throw new \Exception('Cannot create a new MediaObject via API mapping. Use the CreateMediaObjectAction controller instead.'); | |||
| } | |||
| public function populate(object $from, object $to, array $context): object | |||
| { | |||
| // Da MediaObjects nur über den Controller erstellt/aktualisiert werden sollten, | |||
| // müssen wir hier nichts tun | |||
| return $to; | |||
| } | |||
| } | |||
| @@ -0,0 +1,86 @@ | |||
| <?php | |||
| namespace App\Repository; | |||
| use App\Entity\MediaObject; | |||
| use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; | |||
| use Doctrine\Persistence\ManagerRegistry; | |||
| /** | |||
| * @extends ServiceEntityRepository<MediaObject> | |||
| * | |||
| * @method MediaObject|null find($id, $lockMode = null, $lockVersion = null) | |||
| * @method MediaObject|null findOneBy(array $criteria, array $orderBy = null) | |||
| * @method MediaObject[] findAll() | |||
| * @method MediaObject[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) | |||
| */ | |||
| class MediaObjectRepository extends ServiceEntityRepository | |||
| { | |||
| public function __construct(ManagerRegistry $registry) | |||
| { | |||
| parent::__construct($registry, MediaObject::class); | |||
| } | |||
| /** | |||
| * Find media objects created by a specific user | |||
| * | |||
| * @param int $userId | |||
| * @return MediaObject[] | |||
| */ | |||
| public function findByUser(int $userId): array | |||
| { | |||
| return $this->createQueryBuilder('m') | |||
| ->andWhere('m.createdBy = :userId') | |||
| ->setParameter('userId', $userId) | |||
| ->orderBy('m.createdAt', 'DESC') | |||
| ->getQuery() | |||
| ->getResult(); | |||
| } | |||
| /** | |||
| * Find recent media objects with limit | |||
| * | |||
| * @param int $limit | |||
| * @return MediaObject[] | |||
| */ | |||
| public function findRecent(int $limit = 10): array | |||
| { | |||
| return $this->createQueryBuilder('m') | |||
| ->orderBy('m.createdAt', 'DESC') | |||
| ->setMaxResults($limit) | |||
| ->getQuery() | |||
| ->getResult(); | |||
| } | |||
| /** | |||
| * Save media object to database | |||
| * | |||
| * @param MediaObject $mediaObject | |||
| * @param bool $flush Whether to immediately flush changes | |||
| * @return void | |||
| */ | |||
| public function save(MediaObject $mediaObject, bool $flush = true): void | |||
| { | |||
| $this->getEntityManager()->persist($mediaObject); | |||
| if ($flush) { | |||
| $this->getEntityManager()->flush(); | |||
| } | |||
| } | |||
| /** | |||
| * Remove media object from database | |||
| * | |||
| * @param MediaObject $mediaObject | |||
| * @param bool $flush Whether to immediately flush changes | |||
| * @return void | |||
| */ | |||
| public function remove(MediaObject $mediaObject, bool $flush = true): void | |||
| { | |||
| $this->getEntityManager()->remove($mediaObject); | |||
| if ($flush) { | |||
| $this->getEntityManager()->flush(); | |||
| } | |||
| } | |||
| } | |||