3 Commits
Author SHA1 Message Date
Daniel-Garmig 34ecf58097 EasyAdmin - Implemetanción inicial.
Añadido menú para gestionar las Categorias.
2024-04-22 20:15:44 +02:00
Daniel-Garmig fcfe2f9250 New API - RoomCategory 2024-04-22 18:10:16 +02:00
Daniel-Garmig 2079188760 Added Doctrine ORM and dependencies. 2024-04-20 23:34:21 +02:00
38 changed files with 5180 additions and 4 deletions
+10
View File
@@ -18,3 +18,13 @@
APP_ENV=dev APP_ENV=dev
APP_SECRET=d130654a5d6a8ab5945b20b22dfeee74 APP_SECRET=d130654a5d6a8ab5945b20b22dfeee74
###< symfony/framework-bundle ### ###< symfony/framework-bundle ###
###> doctrine/doctrine-bundle ###
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
#
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
# DATABASE_URL="mysql://app:[email protected]:3306/app?serverVersion=8.0.32&charset=utf8mb4"
# DATABASE_URL="mysql://app:[email protected]:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
DATABASE_URL="postgresql://app:[email protected]:54195/app?serverVersion=16&charset=utf8"
###< doctrine/doctrine-bundle ###
+3
View File
@@ -35,6 +35,9 @@ RUN set -eux; \
ENV COMPOSER_ALLOW_SUPERUSER=1 ENV COMPOSER_ALLOW_SUPERUSER=1
###> recipes ### ###> recipes ###
###> doctrine/doctrine-bundle ###
RUN install-php-extensions pdo_pgsql
###< doctrine/doctrine-bundle ###
###< recipes ### ###< recipes ###
COPY --link frankenphp/conf.d/app.ini $PHP_INI_DIR/conf.d/ COPY --link frankenphp/conf.d/app.ini $PHP_INI_DIR/conf.d/
+7 -1
View File
@@ -10,7 +10,7 @@ services:
- ./frankenphp/conf.d/app.dev.ini:/usr/local/etc/php/conf.d/app.dev.ini:ro - ./frankenphp/conf.d/app.dev.ini:/usr/local/etc/php/conf.d/app.dev.ini:ro
# If you develop on Mac or Windows you can remove the vendor/ directory # If you develop on Mac or Windows you can remove the vendor/ directory
# from the bind-mount for better performance by enabling the next line: # from the bind-mount for better performance by enabling the next line:
#- /app/vendor - /app/vendor
environment: environment:
MERCURE_EXTRA_DIRECTIVES: demo MERCURE_EXTRA_DIRECTIVES: demo
# See https://xdebug.org/docs/all_settings#mode # See https://xdebug.org/docs/all_settings#mode
@@ -22,3 +22,9 @@ services:
###> symfony/mercure-bundle ### ###> symfony/mercure-bundle ###
###< symfony/mercure-bundle ### ###< symfony/mercure-bundle ###
###> doctrine/doctrine-bundle ###
database:
ports:
- 54195:5432
###< doctrine/doctrine-bundle ###
+23
View File
@@ -38,8 +38,31 @@ services:
###> symfony/mercure-bundle ### ###> symfony/mercure-bundle ###
###< symfony/mercure-bundle ### ###< symfony/mercure-bundle ###
###> doctrine/doctrine-bundle ###
database:
image: postgres:${POSTGRES_VERSION:-16}-alpine
environment:
POSTGRES_DB: ${POSTGRES_DB:-app}
# You should definitely change the password in production
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!}
POSTGRES_USER: ${POSTGRES_USER:-app}
healthcheck:
test: ["CMD", "pg_isready"]
timeout: 5s
retries: 5
start_period: 60s
volumes:
- database_data:/var/lib/postgresql/data:rw
# You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
# - ./docker/db/data:/var/lib/postgresql/data:rw
###< doctrine/doctrine-bundle ###
volumes: volumes:
caddy_data: caddy_data:
caddy_config: caddy_config:
###> symfony/mercure-bundle ### ###> symfony/mercure-bundle ###
###< symfony/mercure-bundle ### ###< symfony/mercure-bundle ###
###> doctrine/doctrine-bundle ###
database_data:
###< doctrine/doctrine-bundle ###
+17 -1
View File
@@ -1,5 +1,5 @@
{ {
"name": "dgm/instant-rooms", "name": "dgm/somnia-rooms",
"type": "project", "type": "project",
"license": "GPL-3.0", "license": "GPL-3.0",
"description": "A FOSS Hotel room booking system.", "description": "A FOSS Hotel room booking system.",
@@ -9,12 +9,23 @@
"php": ">=8.3.6", "php": ">=8.3.6",
"ext-ctype": "*", "ext-ctype": "*",
"ext-iconv": "*", "ext-iconv": "*",
"doctrine/dbal": "^3",
"doctrine/doctrine-bundle": "^2.12",
"doctrine/doctrine-migrations-bundle": "^3.3",
"doctrine/orm": "^3.1",
"easycorp/easyadmin-bundle": "^4.10",
"phpdocumentor/reflection-docblock": "^5.4",
"phpstan/phpdoc-parser": "^1.28",
"runtime/frankenphp-symfony": "^0.2.0", "runtime/frankenphp-symfony": "^0.2.0",
"symfony/console": "7.0.*", "symfony/console": "7.0.*",
"symfony/dotenv": "7.0.*", "symfony/dotenv": "7.0.*",
"symfony/flex": "^2", "symfony/flex": "^2",
"symfony/framework-bundle": "7.0.*", "symfony/framework-bundle": "7.0.*",
"symfony/property-access": "7.0.*",
"symfony/property-info": "7.0.*",
"symfony/runtime": "7.0.*", "symfony/runtime": "7.0.*",
"symfony/security-bundle": "7.0.*",
"symfony/serializer": "7.0.*",
"symfony/yaml": "7.0.*" "symfony/yaml": "7.0.*"
}, },
"config": { "config": {
@@ -66,5 +77,10 @@
"require": "7.0.*", "require": "7.0.*",
"docker": true "docker": true
} }
},
"require-dev": {
"symfony/maker-bundle": "^1.58",
"symfony/stopwatch": "7.0.*",
"symfony/web-profiler-bundle": "7.0.*"
} }
} }
Generated
+3943 -2
View File
File diff suppressed because it is too large Load Diff
+7
View File
@@ -2,4 +2,11 @@
return [ return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle::class => ['all' => true],
]; ];
+52
View File
@@ -0,0 +1,52 @@
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
# IMPORTANT: You MUST configure your server version,
# either here or in the DATABASE_URL env var (see .env file)
#server_version: '16'
profiling_collect_backtrace: '%kernel.debug%'
use_savepoints: true
orm:
auto_generate_proxy_classes: true
enable_lazy_ghost_objects: true
report_fields_where_declared: true
validate_xml_mapping: true
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: true
mappings:
App:
type: attribute
is_bundle: false
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
controller_resolver:
auto_mapping: true
when@test:
doctrine:
dbal:
# "TEST_TOKEN" is typically set by ParaTest
dbname_suffix: '_test%env(default::TEST_TOKEN)%'
when@prod:
doctrine:
orm:
auto_generate_proxy_classes: false
proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies'
query_cache_driver:
type: pool
pool: doctrine.system_cache_pool
result_cache_driver:
type: pool
pool: doctrine.result_cache_pool
framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app
doctrine.system_cache_pool:
adapter: cache.system
+6
View File
@@ -0,0 +1,6 @@
doctrine_migrations:
migrations_paths:
# namespace is arbitrary but should be different from App\Migrations
# as migrations classes should NOT be autoloaded
'DoctrineMigrations': '%kernel.project_dir%/migrations'
enable_profiler: false
+43
View File
@@ -0,0 +1,43 @@
security:
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\User
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: app_user_provider
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#the-firewall
# https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
when@test:
security:
password_hashers:
# By default, password hashers are resource intensive and take time. This is
# important to generate secure password hashes. In tests however, secure hashes
# are not important, waste resources and increase test times. The following
# reduces the work factor to the lowest possible values.
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
algorithm: auto
cost: 4 # Lowest possible value for bcrypt
time_cost: 3 # Lowest possible value for argon
memory_cost: 10 # Lowest possible value for argon
+7
View File
@@ -0,0 +1,7 @@
framework:
default_locale: en
translator:
default_path: '%kernel.project_dir%/translations'
fallbacks:
- en
providers:
+6
View File
@@ -0,0 +1,6 @@
twig:
file_name_pattern: '*.twig'
when@test:
twig:
strict_variables: true
+11
View File
@@ -0,0 +1,11 @@
framework:
validation:
# Enables validator auto-mapping support.
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
#auto_mapping:
# App\Entity\: []
when@test:
framework:
validation:
not_compromised_password: false
+17
View File
@@ -0,0 +1,17 @@
when@dev:
web_profiler:
toolbar: true
intercept_redirects: false
framework:
profiler:
only_exceptions: false
collect_serializer_data: true
when@test:
web_profiler:
toolbar: false
intercept_redirects: false
framework:
profiler: { collect: false }
+3
View File
@@ -0,0 +1,3 @@
_security_logout:
resource: security.route_loader.logout
type: service
+8
View File
@@ -0,0 +1,8 @@
when@dev:
web_profiler_wdt:
resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
prefix: /_wdt
web_profiler_profiler:
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
prefix: /_profiler
View File
+48
View File
@@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20240420232815 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SEQUENCE room_category_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE room_category_details_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE room_category_photo_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE TABLE room_category (id INT NOT NULL, name VARCHAR(64) NOT NULL, description TEXT DEFAULT NULL, bed_type VARCHAR(64) DEFAULT NULL, max_guest_num INT NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE TABLE room_category_details (id INT NOT NULL, room_category_id INT NOT NULL, details_section VARCHAR(255) NOT NULL, detail_value VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE INDEX IDX_3735FABB67333DD ON room_category_details (room_category_id)');
$this->addSql('CREATE TABLE room_category_photo (id INT NOT NULL, room_category_id INT NOT NULL, path VARCHAR(255) NOT NULL, alt_text VARCHAR(255) DEFAULT NULL, kind VARCHAR(30) NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE INDEX IDX_B5843CAC67333DD ON room_category_photo (room_category_id)');
$this->addSql('ALTER TABLE room_category_details ADD CONSTRAINT FK_3735FABB67333DD FOREIGN KEY (room_category_id) REFERENCES room_category (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE room_category_photo ADD CONSTRAINT FK_B5843CAC67333DD FOREIGN KEY (room_category_id) REFERENCES room_category (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SCHEMA public');
$this->addSql('DROP SEQUENCE room_category_id_seq CASCADE');
$this->addSql('DROP SEQUENCE room_category_details_id_seq CASCADE');
$this->addSql('DROP SEQUENCE room_category_photo_id_seq CASCADE');
$this->addSql('ALTER TABLE room_category_details DROP CONSTRAINT FK_3735FABB67333DD');
$this->addSql('ALTER TABLE room_category_photo DROP CONSTRAINT FK_B5843CAC67333DD');
$this->addSql('DROP TABLE room_category');
$this->addSql('DROP TABLE room_category_details');
$this->addSql('DROP TABLE room_category_photo');
}
}
+35
View File
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20240422163212 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SEQUENCE "user_id_seq" INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE TABLE "user" (id INT NOT NULL, username VARCHAR(180) NOT NULL, roles JSON NOT NULL, password VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE UNIQUE INDEX UNIQ_IDENTIFIER_USERNAME ON "user" (username)');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SCHEMA public');
$this->addSql('DROP SEQUENCE "user_id_seq" CASCADE');
$this->addSql('DROP TABLE "user"');
}
}
@@ -0,0 +1,38 @@
<?php
namespace App\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Field\Field;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
use EasyCorp\Bundle\EasyAdminBundle\Field\CollectionField;
use App\Entity\RoomCategory;
class RoomCategoryCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return RoomCategory::class;
}
public function configureCrud(Crud $crud): Crud
{
return $crud;
}
public function configureFields(string $pageName): iterable
{
return [
TextField::new('name'),
TextEditorField::new('description'),
TextField::new('bedType'),
IntegerField::new('maxGuestNum'),
CollectionField::new('roomCategoryDetails')->useEntryCrudForm(),
CollectionField::new('roomCategoryPhotos')->useEntryCrudForm()
];
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Controller\Admin;
use App\Entity\RoomCategoryDetails;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
class RoomCategoryDetailsCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return RoomCategoryDetails::class;
}
public function configureFields(string $pageName): iterable
{
return [
TextField::new('detailsSection'),
TextEditorField::new('detailValue'),
];
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Controller\Admin;
use App\Entity\RoomCategoryPhoto;
use App\Entity\RoomCategoryPhotoKinds;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
class RoomCategoryPhotoCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return RoomCategoryPhoto::class;
}
public function configureFields(string $pageName): iterable
{
yield TextField::new('path');
yield TextEditorField::new('altText');
yield ChoiceField::new('kind')->setChoices(['Main' => 'main', 'Bathroom' => 'bathroom', 'Other' => 'other']);
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Entity\RoomCategory;
class SomniaDashboardController extends AbstractDashboardController
{
#[Route('/admin', name: 'admin')]
public function index(): Response
{
return $this->render('admin/somniaDashboard.html.twig');
}
public function configureDashboard(): Dashboard
{
return Dashboard::new()
->setTitle('SomniaRooms');
}
public function configureMenuItems(): iterable
{
yield MenuItem::linkToDashboard('Dashboard', 'fa fa-home');
yield MenuItem::Section('Room Management');
yield MenuItem::linkToCrud('Category', 'fas fa-list', RoomCategory::class);
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Doctrine\ORM\EntityManagerInterface;
use App\Repository\RoomCategoryRepository;
use App\Entity\RoomCategory;
use App\Entity\RoomCategoryDetails;
use App\Entity\RoomCategoryPhoto;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Serializer\Context\Normalizer\ObjectNormalizerContextBuilder;
class RoomCategoryController extends AbstractController
{
#[Route('/room/category', name: 'app_room_category')]
public function getAll(RoomCategoryRepository $catRepo, SerializerInterface $serializer): Response
{
$catList = $catRepo->findAll();
return $this->json(["results" => $catList]);
}
#[Route('/room/category/{id}', name: 'app_room_category')]
public function getById(RoomCategory $category, SerializerInterface $serializer): Response
{
return $this->json($category);
}
}
View File
+162
View File
@@ -0,0 +1,162 @@
<?php
namespace App\Entity;
use App\Repository\RoomCategoryRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Serializer\Annotation\Ignore;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: RoomCategoryRepository::class)]
class RoomCategory
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 64)]
private ?string $name = null;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $description = null;
#[ORM\Column(length: 64, nullable: true)]
private ?string $bedType = null;
#[ORM\Column]
private ?int $maxGuestNum = null;
/**
* @var Collection<int, RoomCategoryPhoto>
*/
#[ORM\OneToMany(targetEntity: RoomCategoryPhoto::class, mappedBy: 'roomCategory', orphanRemoval: true, cascade: ['persist'])]
private Collection $roomCategoryPhotos;
/**
* @var Collection<int, RoomCategoryDetails>
*/
#[ORM\OneToMany(targetEntity: RoomCategoryDetails::class, mappedBy: 'roomCategory', orphanRemoval: true, cascade: ['persist'])]
private Collection $roomCategoryDetails;
public function __construct()
{
$this->roomCategoryPhotos = new ArrayCollection();
$this->roomCategoryDetails = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): static
{
$this->description = $description;
return $this;
}
public function getBedType(): ?string
{
return $this->bedType;
}
public function setBedType(?string $bedType): static
{
$this->bedType = $bedType;
return $this;
}
public function getMaxGuestNum(): ?int
{
return $this->maxGuestNum;
}
public function setMaxGuestNum(int $maxGuestNum): static
{
$this->maxGuestNum = $maxGuestNum;
return $this;
}
/**
* @return Collection<int, RoomCategoryPhoto>
*/
public function getRoomCategoryPhotos(): Collection
{
return $this->roomCategoryPhotos;
}
public function addRoomCategoryPhoto(RoomCategoryPhoto $roomCategoryPhoto): static
{
if (!$this->roomCategoryPhotos->contains($roomCategoryPhoto)) {
$this->roomCategoryPhotos->add($roomCategoryPhoto);
$roomCategoryPhoto->setRoomCategory($this);
}
return $this;
}
public function removeRoomCategoryPhoto(RoomCategoryPhoto $roomCategoryPhoto): static
{
if ($this->roomCategoryPhotos->removeElement($roomCategoryPhoto)) {
// set the owning side to null (unless already changed)
if ($roomCategoryPhoto->getRoomCategory() === $this) {
$roomCategoryPhoto->setRoomCategory(null);
}
}
return $this;
}
/**
* @return Collection<int, RoomCategoryDetails>
*/
public function getRoomCategoryDetails(): Collection
{
return $this->roomCategoryDetails;
}
public function addRoomCategoryDetail(RoomCategoryDetails $roomCategoryDetail): static
{
if (!$this->roomCategoryDetails->contains($roomCategoryDetail)) {
$this->roomCategoryDetails->add($roomCategoryDetail);
$roomCategoryDetail->setRoomCategory($this);
}
return $this;
}
public function removeRoomCategoryDetail(RoomCategoryDetails $roomCategoryDetail): static
{
if ($this->roomCategoryDetails->removeElement($roomCategoryDetail)) {
// set the owning side to null (unless already changed)
if ($roomCategoryDetail->getRoomCategory() === $this) {
$roomCategoryDetail->setRoomCategory(null);
}
}
return $this;
}
}
+70
View File
@@ -0,0 +1,70 @@
<?php
namespace App\Entity;
use App\Repository\RoomCategoryDetailsRepository;
use Symfony\Component\Serializer\Annotation\Ignore;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: RoomCategoryDetailsRepository::class)]
class RoomCategoryDetails
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $detailsSection = null;
#[ORM\Column(length: 255)]
private ?string $detailValue = null;
#[ORM\ManyToOne(inversedBy: 'roomCategoryDetails')]
#[ORM\JoinColumn(nullable: false)]
#[Ignore]
private ?RoomCategory $roomCategory = null;
public function getId(): ?int
{
return $this->id;
}
public function getDetailsSection(): ?string
{
return $this->detailsSection;
}
public function setDetailsSection(string $detailsSection): static
{
$this->detailsSection = $detailsSection;
return $this;
}
public function getDetailValue(): ?string
{
return $this->detailValue;
}
public function setDetailValue(string $detailValue): static
{
$this->detailValue = $detailValue;
return $this;
}
#[Ignore]
public function getRoomCategory(): ?RoomCategory
{
return $this->roomCategory;
}
#[Ignore]
public function setRoomCategory(?RoomCategory $roomCategory): static
{
$this->roomCategory = $roomCategory;
return $this;
}
}
+85
View File
@@ -0,0 +1,85 @@
<?php
namespace App\Entity;
use App\Repository\RoomCategoryPhotoRepository;
use Symfony\Component\Serializer\Annotation\Ignore;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: RoomCategoryPhotoRepository::class)]
class RoomCategoryPhoto
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $path = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $altText = null;
#[ORM\Column(length: 30)]
private ?string $kind = null;
#[ORM\ManyToOne(inversedBy: 'roomCategoryPhotos')]
#[ORM\JoinColumn(nullable: false)]
#[Ignore]
private ?RoomCategory $roomCategory = null;
public function getId(): ?int
{
return $this->id;
}
public function getPath(): ?string
{
return $this->path;
}
public function setPath(string $path): static
{
$this->path = $path;
return $this;
}
public function getAltText(): ?string
{
return $this->altText;
}
public function setAltText(?string $altText): static
{
$this->altText = $altText;
return $this;
}
public function getKind(): ?string
{
return $this->kind;
}
public function setKind(string $kind): static
{
$this->kind = $kind;
return $this;
}
#[Ignore]
public function getRoomCategory(): ?RoomCategory
{
return $this->roomCategory;
}
#[Ignore]
public function setRoomCategory(?RoomCategory $roomCategory): static
{
$this->roomCategory = $roomCategory;
return $this;
}
}
+109
View File
@@ -0,0 +1,109 @@
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\Table(name: '`user`')]
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_USERNAME', fields: ['username'])]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 180)]
private ?string $username = null;
/**
* @var list<string> The user roles
*/
#[ORM\Column]
private array $roles = [];
/**
* @var string The hashed password
*/
#[ORM\Column]
private ?string $password = null;
public function getId(): ?int
{
return $this->id;
}
public function getUsername(): ?string
{
return $this->username;
}
public function setUsername(string $username): static
{
$this->username = $username;
return $this;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->username;
}
/**
* @see UserInterface
*
* @return list<string>
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
/**
* @param list<string> $roles
*/
public function setRoles(array $roles): static
{
$this->roles = $roles;
return $this;
}
/**
* @see PasswordAuthenticatedUserInterface
*/
public function getPassword(): string
{
return $this->password;
}
public function setPassword(string $password): static
{
$this->password = $password;
return $this;
}
/**
* @see UserInterface
*/
public function eraseCredentials(): void
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
}
View File
@@ -0,0 +1,48 @@
<?php
namespace App\Repository;
use App\Entity\RoomCategoryDetails;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<RoomCategoryDetails>
*
* @method RoomCategoryDetails|null find($id, $lockMode = null, $lockVersion = null)
* @method RoomCategoryDetails|null findOneBy(array $criteria, array $orderBy = null)
* @method RoomCategoryDetails[] findAll()
* @method RoomCategoryDetails[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class RoomCategoryDetailsRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, RoomCategoryDetails::class);
}
// /**
// * @return RoomCategoryDetails[] Returns an array of RoomCategoryDetails objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('r')
// ->andWhere('r.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('r.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?RoomCategoryDetails
// {
// return $this->createQueryBuilder('r')
// ->andWhere('r.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
@@ -0,0 +1,48 @@
<?php
namespace App\Repository;
use App\Entity\RoomCategoryPhoto;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<RoomCategoryPhoto>
*
* @method RoomCategoryPhoto|null find($id, $lockMode = null, $lockVersion = null)
* @method RoomCategoryPhoto|null findOneBy(array $criteria, array $orderBy = null)
* @method RoomCategoryPhoto[] findAll()
* @method RoomCategoryPhoto[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class RoomCategoryPhotoRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, RoomCategoryPhoto::class);
}
// /**
// * @return RoomCategoryPhoto[] Returns an array of RoomCategoryPhoto objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('r')
// ->andWhere('r.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('r.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?RoomCategoryPhoto
// {
// return $this->createQueryBuilder('r')
// ->andWhere('r.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
+48
View File
@@ -0,0 +1,48 @@
<?php
namespace App\Repository;
use App\Entity\RoomCategory;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<RoomCategory>
*
* @method RoomCategory|null find($id, $lockMode = null, $lockVersion = null)
* @method RoomCategory|null findOneBy(array $criteria, array $orderBy = null)
* @method RoomCategory[] findAll()
* @method RoomCategory[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class RoomCategoryRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, RoomCategory::class);
}
// /**
// * @return RoomCategory[] Returns an array of RoomCategory objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('r')
// ->andWhere('r.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('r.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?RoomCategory
// {
// return $this->createQueryBuilder('r')
// ->andWhere('r.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
+65
View File
@@ -0,0 +1,65 @@
<?php
namespace App\Repository;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
/**
* @extends ServiceEntityRepository<User>
*
* @method User|null find($id, $lockMode = null, $lockVersion = null)
* @method User|null findOneBy(array $criteria, array $orderBy = null)
* @method User[] findAll()
* @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, User::class);
}
/**
* Used to upgrade (rehash) the user's password automatically over time.
*/
public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
{
if (!$user instanceof User) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class));
}
$user->setPassword($newHashedPassword);
$this->getEntityManager()->persist($user);
$this->getEntityManager()->flush();
}
// /**
// * @return User[] Returns an array of User objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('u')
// ->andWhere('u.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('u.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?User
// {
// return $this->createQueryBuilder('u')
// ->andWhere('u.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
+118
View File
@@ -1,4 +1,40 @@
{ {
"doctrine/doctrine-bundle": {
"version": "2.12",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.12",
"ref": "32f890075233ac4a1176e848a0f8e932ac6536d6"
},
"files": [
"./config/packages/doctrine.yaml",
"./src/Entity/.gitignore",
"./src/Repository/.gitignore"
]
},
"doctrine/doctrine-migrations-bundle": {
"version": "3.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.1",
"ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33"
},
"files": [
"./config/packages/doctrine_migrations.yaml",
"./migrations/.gitignore"
]
},
"easycorp/easyadmin-bundle": {
"version": "4.10",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.0",
"ref": "b131e6cbfe1b898a508987851963fff485986285"
}
},
"symfony/console": { "symfony/console": {
"version": "7.0", "version": "7.0",
"recipe": { "recipe": {
@@ -42,6 +78,15 @@
"src/Kernel.php" "src/Kernel.php"
] ]
}, },
"symfony/maker-bundle": {
"version": "1.58",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
}
},
"symfony/routing": { "symfony/routing": {
"version": "7.0", "version": "7.0",
"recipe": { "recipe": {
@@ -54,5 +99,78 @@
"config/packages/routing.yaml", "config/packages/routing.yaml",
"config/routes.yaml" "config/routes.yaml"
] ]
},
"symfony/security-bundle": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.4",
"ref": "2ae08430db28c8eb4476605894296c82a642028f"
},
"files": [
"./config/packages/security.yaml",
"./config/routes/security.yaml"
]
},
"symfony/translation": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.3",
"ref": "e28e27f53663cc34f0be2837aba18e3a1bef8e7b"
},
"files": [
"./config/packages/translation.yaml",
"./translations/.gitignore"
]
},
"symfony/twig-bundle": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.4",
"ref": "cab5fd2a13a45c266d45a7d9337e28dee6272877"
},
"files": [
"./config/packages/twig.yaml",
"./templates/base.html.twig"
]
},
"symfony/uid": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.0",
"ref": "0df5844274d871b37fc3816c57a768ffc60a43a5"
}
},
"symfony/validator": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.0",
"ref": "8c1c4e28d26a124b0bb273f537ca8ce443472bfd"
},
"files": [
"./config/packages/validator.yaml"
]
},
"symfony/web-profiler-bundle": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.1",
"ref": "e42b3f0177df239add25373083a564e5ead4e13a"
},
"files": [
"./config/packages/web_profiler.yaml",
"./config/routes/web_profiler.yaml"
]
} }
} }
@@ -0,0 +1,6 @@
{# templates/admin/somniaDashboard.html.html.twig #}
{% extends '@EasyAdmin/layout.html.twig' %}
{% block main %}
{# ... #}
{% endblock main %}
+16
View File
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text><text y=%221.3em%22 x=%220.2em%22 font-size=%2276%22 fill=%22%23fff%22>sf</text></svg>">
{% block stylesheets %}
{% endblock %}
{% block javascripts %}
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
View File