Initial commit
This commit is contained in:
44
.env
Normal file
44
.env
Normal file
@ -0,0 +1,44 @@
|
||||
# In all environments, the following files are loaded if they exist,
|
||||
# the latter taking precedence over the former:
|
||||
#
|
||||
# * .env contains default values for the environment variables needed by the app
|
||||
# * .env.local uncommitted file with local overrides
|
||||
# * .env.$APP_ENV committed environment-specific defaults
|
||||
# * .env.$APP_ENV.local uncommitted environment-specific overrides
|
||||
#
|
||||
# Real environment variables win over .env files.
|
||||
#
|
||||
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
|
||||
#
|
||||
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
|
||||
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
|
||||
|
||||
###> symfony/framework-bundle ###
|
||||
APP_ENV=dev
|
||||
APP_SECRET=********************************
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
###> symfony/webapp-meta ###
|
||||
MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
|
||||
###< symfony/webapp-meta ###
|
||||
|
||||
###> 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://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7&charset=utf8mb4"
|
||||
# DATABASE_URL="postgresql://symfony:ChangeMe@127.0.0.1:5432/app?serverVersion=13&charset=utf8"
|
||||
DATABASE_URL="mysql://username:password@127.0.0.1:3306/database?serverVersion=8.0&charset=utf8mb4"
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
###> symfony/messenger ###
|
||||
# Choose one of the transports below
|
||||
# MESSENGER_TRANSPORT_DSN=doctrine://default
|
||||
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
|
||||
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
|
||||
###< symfony/messenger ###
|
||||
|
||||
###> symfony/mailer ###
|
||||
# MAILER_DSN=smtp://localhost
|
||||
###< symfony/mailer ###
|
||||
72
.gitignore
vendored
72
.gitignore
vendored
@ -1,54 +1,26 @@
|
||||
# ---> Symfony
|
||||
# Cache and logs (Symfony2)
|
||||
/app/cache/*
|
||||
/app/logs/*
|
||||
!app/cache/.gitkeep
|
||||
!app/logs/.gitkeep
|
||||
|
||||
# Email spool folder
|
||||
/app/spool/*
|
||||
|
||||
# Cache, session files and logs (Symfony3)
|
||||
/var/cache/*
|
||||
/var/logs/*
|
||||
/var/sessions/*
|
||||
!var/cache/.gitkeep
|
||||
!var/logs/.gitkeep
|
||||
!var/sessions/.gitkeep
|
||||
|
||||
# Logs (Symfony4)
|
||||
/var/log/*
|
||||
!var/log/.gitkeep
|
||||
|
||||
# Parameters
|
||||
/app/config/parameters.yml
|
||||
/app/config/parameters.ini
|
||||
|
||||
# Managed by Composer
|
||||
/app/bootstrap.php.cache
|
||||
/var/bootstrap.php.cache
|
||||
/bin/*
|
||||
!bin/console
|
||||
!bin/symfony_requirements
|
||||
###> symfony/framework-bundle ###
|
||||
/.env.local
|
||||
/.env.local.php
|
||||
/.env.*.local
|
||||
/config/secrets/prod/prod.decrypt.private.php
|
||||
/public/bundles/
|
||||
/var/
|
||||
/vendor/
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
# Assets and user uploads
|
||||
/web/bundles/
|
||||
/web/uploads/
|
||||
|
||||
# PHPUnit
|
||||
/app/phpunit.xml
|
||||
/phpunit.xml
|
||||
|
||||
# Build data
|
||||
/build/
|
||||
|
||||
# Composer PHAR
|
||||
/composer.phar
|
||||
|
||||
# Backup entities generated with doctrine:generate:entities command
|
||||
**/Entity/*~
|
||||
|
||||
# Embedded web-server pid file
|
||||
/.web-server-pid
|
||||
###> symfony/webpack-encore-bundle ###
|
||||
/node_modules/
|
||||
/public/build/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
###< symfony/webpack-encore-bundle ###
|
||||
|
||||
/_sql/
|
||||
/.yarn/
|
||||
/assets/static/
|
||||
/public/.well-known/
|
||||
/public/android/
|
||||
/public/upload/
|
||||
/public/yandex_678f0b750d297325.html
|
||||
/public/BingSiteAuth.xml
|
||||
|
||||
1
.yarnrc.yml
Normal file
1
.yarnrc.yml
Normal file
@ -0,0 +1 @@
|
||||
nodeLinker: node-modules
|
||||
2889
assets/app.js
Normal file
2889
assets/app.js
Normal file
File diff suppressed because it is too large
Load Diff
27
assets/css/_vars.scss
Normal file
27
assets/css/_vars.scss
Normal file
@ -0,0 +1,27 @@
|
||||
$cl_black: rgb(0, 0, 0);
|
||||
$cl_gray: rgb(128, 128, 128);
|
||||
$cl_white: rgb(255, 255, 255);
|
||||
|
||||
$cl_anemo: rgb(39, 161, 146);
|
||||
$cl_pyro: rgb(190, 40, 40);
|
||||
$cl_hydro: rgb(34, 143, 186);
|
||||
$cl_electro: rgb(109, 81, 184);
|
||||
$cl_cryo: rgb(128, 172, 211);
|
||||
$cl_dendro: rgb(83, 153, 100);
|
||||
$cl_geo: rgb(214, 153, 64);
|
||||
|
||||
$cl_common: rgb(55, 180, 140);
|
||||
$cl_rare: rgb(80, 130, 205);
|
||||
$cl_epic: rgb(160, 65, 225);
|
||||
$cl_legendary: rgb(215, 125, 55);
|
||||
$cl_challenge: rgb(190, 40, 40);
|
||||
$cl_seelie: rgb(25, 225, 215);
|
||||
|
||||
$cl_sand: rgb(120, 106, 80);
|
||||
$cl_sea: rgb(27, 40, 59);
|
||||
|
||||
$cl_ui_dark: rgb(74, 83, 102);
|
||||
$cl_ui_darker: rgb(40, 46, 61);
|
||||
$cl_ui_shell: rgb(183, 186, 194);
|
||||
$cl_ui_light: rgb(236, 229, 216);
|
||||
$cl_ui_hover: rgb(217, 167, 98);
|
||||
31
assets/css/font.scss
Normal file
31
assets/css/font.scss
Normal file
@ -0,0 +1,31 @@
|
||||
@font-face {
|
||||
font-family: 'ptsans_regular';
|
||||
src: url('../font/ptsans-regular.woff2') format('woff2'),
|
||||
url('../font/ptsans-regular.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'ptsans_bold';
|
||||
src: url('../font/ptsans-bold.woff2') format('woff2'),
|
||||
url('../font/ptsans-bold.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'ptsans_italic';
|
||||
src: url('../font/ptsans-italic.woff2') format('woff2'),
|
||||
url('../font/ptsans-italic.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'ptsans_bold_italic';
|
||||
src: url('../font/ptsans-bolditalic.woff2') format('woff2'),
|
||||
url('../font/ptsans-bolditalic.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
53
assets/css/layout.scss
Normal file
53
assets/css/layout.scss
Normal file
@ -0,0 +1,53 @@
|
||||
body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#page-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
#header-container, #footer-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-shrink: 0;
|
||||
flex-wrap: nowrap;
|
||||
overflow: hidden;
|
||||
padding: 0 20px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#header-container {
|
||||
max-height: 64px;
|
||||
}
|
||||
|
||||
#main-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
flex-wrap: nowrap;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#main-left-container, #main-center-container, #main-right-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#main-left-container, #main-right-container {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
#main-center-container {
|
||||
flex-grow: 1;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#footer-container {
|
||||
max-height: 32px;
|
||||
}
|
||||
198
assets/css/normalize.scss
vendored
Normal file
198
assets/css/normalize.scss
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
font-size: 16px;
|
||||
height: 100vh;
|
||||
line-height: 1.15;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
&:before, &:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
//&:focus {
|
||||
// outline: none;
|
||||
//}
|
||||
}
|
||||
|
||||
body {
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
&:visited, &:hover, &:active, &:focus {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none;
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
|
||||
b, strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
button, input, optgroup, select, textarea {
|
||||
font-family: inherit;
|
||||
font-size: 100%;
|
||||
line-height: 1.15;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button, input {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
button, select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
details {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div, textarea, table, td, th, code, pre, samp {
|
||||
word-wrap: break-word;
|
||||
hyphens: auto;
|
||||
-moz-hyphens: auto;
|
||||
-webkit-hyphens: auto;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
a, button, input, select, textarea {
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
legend {
|
||||
box-sizing: border-box;
|
||||
color: inherit;
|
||||
display: table;
|
||||
max-width: 100%;
|
||||
padding: 0;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
pre, code, kbd, samp {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
sub, sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button, [type="button"], [type="reset"], [type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
&::-moz-focus-inner, &::-moz-focus-inner, &::-moz-focus-inner, &::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
&:-moz-focusring, &:-moz-focusring, &:-moz-focusring, &:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
}
|
||||
|
||||
[type="checkbox"], [type="radio"] {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
[type="number"] {
|
||||
//-moz-appearance: textfield;
|
||||
&::-webkit-inner-spin-button, &::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
//-webkit-appearance: none;
|
||||
}
|
||||
}
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield;
|
||||
outline-offset: -2px;
|
||||
&::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button;
|
||||
font: inherit;
|
||||
}
|
||||
2455
assets/css/style.scss
Normal file
2455
assets/css/style.scss
Normal file
File diff suppressed because it is too large
Load Diff
BIN
assets/font/ptsans-bold.woff
Normal file
BIN
assets/font/ptsans-bold.woff
Normal file
Binary file not shown.
BIN
assets/font/ptsans-bold.woff2
Normal file
BIN
assets/font/ptsans-bold.woff2
Normal file
Binary file not shown.
BIN
assets/font/ptsans-bolditalic.woff
Normal file
BIN
assets/font/ptsans-bolditalic.woff
Normal file
Binary file not shown.
BIN
assets/font/ptsans-bolditalic.woff2
Normal file
BIN
assets/font/ptsans-bolditalic.woff2
Normal file
Binary file not shown.
BIN
assets/font/ptsans-italic.woff
Normal file
BIN
assets/font/ptsans-italic.woff
Normal file
Binary file not shown.
BIN
assets/font/ptsans-italic.woff2
Normal file
BIN
assets/font/ptsans-italic.woff2
Normal file
Binary file not shown.
BIN
assets/font/ptsans-regular.woff
Normal file
BIN
assets/font/ptsans-regular.woff
Normal file
Binary file not shown.
BIN
assets/font/ptsans-regular.woff2
Normal file
BIN
assets/font/ptsans-regular.woff2
Normal file
Binary file not shown.
BIN
assets/img/background.jpg
Normal file
BIN
assets/img/background.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
98
assets/js/Classes/Store.js
Normal file
98
assets/js/Classes/Store.js
Normal file
@ -0,0 +1,98 @@
|
||||
export class Store {
|
||||
/** @private {string} */
|
||||
#_storeName;
|
||||
/** @private {boolean} */
|
||||
#_autoIncrement;
|
||||
/** @private {string|Array} */
|
||||
#_keyPath;
|
||||
/** @private {Object[]} */
|
||||
#_indexes;
|
||||
|
||||
/**
|
||||
* @param {string} storeName
|
||||
* @param {boolean} autoIncrement
|
||||
* @param {string|Array} keyPath
|
||||
* @param {Object[]} indexes
|
||||
*/
|
||||
constructor(storeName, autoIncrement = true, keyPath = "id", indexes = []) {
|
||||
this.#_storeName = storeName;
|
||||
this.#_autoIncrement = autoIncrement;
|
||||
this.#_keyPath = keyPath;
|
||||
this.#_indexes = indexes;
|
||||
}
|
||||
|
||||
get storeName() {
|
||||
return this.#_storeName;
|
||||
}
|
||||
|
||||
set storeName(value) {
|
||||
this.#_storeName = value
|
||||
}
|
||||
|
||||
get autoIncrement() {
|
||||
return this.#_autoIncrement;
|
||||
}
|
||||
|
||||
set autoIncrement(value) {
|
||||
this.#_autoIncrement = value
|
||||
}
|
||||
|
||||
get keyPath() {
|
||||
return this.#_keyPath;
|
||||
}
|
||||
|
||||
set keyPath(value) {
|
||||
this.#_keyPath = value
|
||||
}
|
||||
|
||||
get indexes() {
|
||||
return this.#_indexes;
|
||||
}
|
||||
|
||||
set indexes(value) {
|
||||
this.#_indexes = value
|
||||
}
|
||||
}
|
||||
|
||||
export class Index {
|
||||
/** @private {string} */
|
||||
#_name;
|
||||
/** @private {string} */
|
||||
#_keyPath;
|
||||
/** @private {Object} */
|
||||
#_options = {};
|
||||
|
||||
/**
|
||||
* @param {string} keyPath
|
||||
* @param {boolean} isUnique
|
||||
*/
|
||||
constructor(keyPath, isUnique = false) {
|
||||
this.#_name = keyPath;
|
||||
this.#_keyPath = keyPath;
|
||||
this.#_options = { unique: isUnique};
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.#_name;
|
||||
}
|
||||
|
||||
set name(value) {
|
||||
this.#_name = value;
|
||||
}
|
||||
|
||||
get keyPath() {
|
||||
return this.#_keyPath;
|
||||
}
|
||||
|
||||
set keyPath(value) {
|
||||
this.#_keyPath = value;
|
||||
}
|
||||
|
||||
get options() {
|
||||
return this.#_options;
|
||||
}
|
||||
|
||||
set options(value) {
|
||||
this.#_options = value;
|
||||
}
|
||||
}
|
||||
338
assets/js/Classes/Worldmap.js
Normal file
338
assets/js/Classes/Worldmap.js
Normal file
@ -0,0 +1,338 @@
|
||||
export class Profile {
|
||||
#__type = "class"
|
||||
/** @private {string} */
|
||||
#_slug;
|
||||
/** @private {string} */
|
||||
#_name;
|
||||
/** @private {string} */
|
||||
#_server;
|
||||
/** @private {boolean} */
|
||||
#_isActive;
|
||||
|
||||
/**
|
||||
* @param {string} slug
|
||||
* @param {string} name
|
||||
* @param {string} server
|
||||
* @param {boolean} isActive
|
||||
*/
|
||||
constructor(slug = "", name = "", server = "eu", isActive = true) {
|
||||
this.#_slug = slug;
|
||||
this.#_name = name;
|
||||
this.#_server = server;
|
||||
this.#_isActive = isActive;
|
||||
}
|
||||
|
||||
get __type () {
|
||||
return this.#__type;
|
||||
}
|
||||
|
||||
get slug() {
|
||||
return this.#_slug;
|
||||
}
|
||||
|
||||
set slug(value) {
|
||||
this.#_slug = value;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.#_name;
|
||||
}
|
||||
|
||||
set name(value) {
|
||||
this.#_name = value;
|
||||
}
|
||||
|
||||
get server() {
|
||||
return this.#_server;
|
||||
}
|
||||
|
||||
set server(value) {
|
||||
this.#_server = value;
|
||||
}
|
||||
|
||||
get isActive() {
|
||||
return this.#_isActive;
|
||||
}
|
||||
|
||||
set isActive(value) {
|
||||
this.#_isActive = Boolean(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} slug
|
||||
* @param {string} name
|
||||
* @param {string} server
|
||||
* @param {boolean} isActive
|
||||
*/
|
||||
hydrate({slug, name, server, isActive}) {
|
||||
this.slug = slug;
|
||||
this.name = name;
|
||||
this.server = server;
|
||||
this.isActive = isActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {{slug: string, name: string, server: string, isActive: number}}
|
||||
*/
|
||||
dehydrate() {
|
||||
return {
|
||||
slug: this.slug,
|
||||
name: this.name,
|
||||
server: this.server,
|
||||
isActive: Number(this.isActive)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Region {
|
||||
#__type = "class";
|
||||
/** @private {string} */
|
||||
#_slug;
|
||||
/** @private {string} */
|
||||
#_name;
|
||||
/** @private {number} */
|
||||
#_scrollLeft;
|
||||
/** @private {number} */
|
||||
#_scrollTop;
|
||||
/** @private {number} */
|
||||
#_zoomLevel;
|
||||
|
||||
/**
|
||||
* @param {string} slug
|
||||
* @param {string} name
|
||||
* @param {number} scrollLeft
|
||||
* @param {number} scrollTop
|
||||
* @param {number} zoomLevel
|
||||
*/
|
||||
constructor(slug, name, scrollLeft = 50, scrollTop = 50, zoomLevel = 8) {
|
||||
this.#_slug = slug;
|
||||
this.#_name = name;
|
||||
this.#_scrollLeft = scrollLeft;
|
||||
this.#_scrollTop = scrollTop;
|
||||
this.#_zoomLevel = zoomLevel;
|
||||
}
|
||||
|
||||
get __type () {
|
||||
return this.#__type;
|
||||
}
|
||||
|
||||
get slug() {
|
||||
return this.#_slug;
|
||||
}
|
||||
|
||||
set slug(value) {
|
||||
this.#_slug = value;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.#_name;
|
||||
}
|
||||
|
||||
set name(value) {
|
||||
this.#_name = value;
|
||||
}
|
||||
|
||||
get scrollLeft() {
|
||||
return this.#_scrollLeft;
|
||||
}
|
||||
|
||||
set scrollLeft(value) {
|
||||
this.#_scrollLeft = Number(value);
|
||||
}
|
||||
|
||||
get scrollTop() {
|
||||
return this.#_scrollTop;
|
||||
}
|
||||
|
||||
set scrollTop(value) {
|
||||
this.#_scrollTop = Number(value);
|
||||
}
|
||||
|
||||
get zoomLevel() {
|
||||
return this.#_zoomLevel;
|
||||
}
|
||||
|
||||
set zoomLevel(value) {
|
||||
this.#_zoomLevel = Number(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} slug
|
||||
* @param {string} name
|
||||
* @param {number} scrollLeft
|
||||
* @param {number} scrollTop
|
||||
* @param {number} zoomLevel
|
||||
*/
|
||||
hydrate({slug, name, scrollLeft, scrollTop, zoomLevel}) {
|
||||
this.slug = slug;
|
||||
this.name = name;
|
||||
this.scrollLeft = scrollLeft;
|
||||
this.scrollTop = scrollTop;
|
||||
this.zoomLevel = zoomLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {{slug: string, name: string, scrollLeft: number, scrollTop: number, zoomLevel: number}}
|
||||
*/
|
||||
dehydrate() {
|
||||
return {
|
||||
slug: this.slug,
|
||||
name: this.name,
|
||||
scrollLeft: Number(this.scrollLeft),
|
||||
scrollTop: Number(this.scrollTop),
|
||||
zoomLevel: Number(this.zoomLevel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Filter {
|
||||
#__type = "class";
|
||||
/** @private {string} */
|
||||
#_region;
|
||||
/** @private {string} */
|
||||
#_slug;
|
||||
/** @private {boolean} */
|
||||
#_isActive;
|
||||
|
||||
/**
|
||||
* @param {string} region
|
||||
* @param {string} slug
|
||||
* @param {boolean} isActive
|
||||
*/
|
||||
constructor(region, slug, isActive=false) {
|
||||
this.#_region = region;
|
||||
this.#_slug = slug;
|
||||
this.#_isActive = isActive;
|
||||
}
|
||||
|
||||
get __type () {
|
||||
return this.#__type;
|
||||
}
|
||||
|
||||
get slug() {
|
||||
return this.#_slug;
|
||||
}
|
||||
|
||||
set slug(value) {
|
||||
this.#_slug = value;
|
||||
}
|
||||
|
||||
get region() {
|
||||
return this.#_region;
|
||||
}
|
||||
|
||||
set region(value) {
|
||||
this.#_region = value;
|
||||
}
|
||||
|
||||
get isActive() {
|
||||
return this.#_isActive;
|
||||
}
|
||||
|
||||
set isActive(value) {
|
||||
this.#_isActive = Boolean(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} region
|
||||
* @param {string} slug
|
||||
* @param {boolean} isActive
|
||||
*/
|
||||
hydrate({region, slug, isActive}) {
|
||||
this.region = region
|
||||
this.slug = slug
|
||||
this.isActive = isActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {{region: string, slug: string, isActive: number}}
|
||||
*/
|
||||
dehydrate() {
|
||||
return {
|
||||
region: this.region,
|
||||
slug: this.slug,
|
||||
isActive: Number(this.isActive)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Node {
|
||||
#__type = "class";
|
||||
/** @private {string} */
|
||||
#_profile;
|
||||
/** @private {string} */
|
||||
#_region;
|
||||
/** @private {string} */
|
||||
#_domId;
|
||||
/** @private {boolean} */
|
||||
#_isHidden;
|
||||
|
||||
constructor(profile, id, region, isHidden) {
|
||||
this.#_profile = profile;
|
||||
this.#_domId = id;
|
||||
this.#_region = region;
|
||||
this.#_isHidden = isHidden;
|
||||
|
||||
}
|
||||
|
||||
get __type () {
|
||||
return this.#__type;
|
||||
}
|
||||
|
||||
get profile() {
|
||||
return this.#_profile;
|
||||
}
|
||||
|
||||
set profile(value) {
|
||||
this.#_profile = value;
|
||||
}
|
||||
|
||||
get region() {
|
||||
return this.#_region;
|
||||
}
|
||||
|
||||
set region(value) {
|
||||
this.#_region = value;
|
||||
}
|
||||
|
||||
get domId() {
|
||||
return this.#_domId;
|
||||
}
|
||||
|
||||
set domId(value) {
|
||||
this.#_domId = value;
|
||||
}
|
||||
|
||||
get isHidden() {
|
||||
return this.#_isHidden;
|
||||
}
|
||||
|
||||
set isHidden(value) {
|
||||
this.#_isHidden = Boolean(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} profile
|
||||
* @param {string} domId
|
||||
* @param {string} region
|
||||
* @param {boolean} isHidden
|
||||
*/
|
||||
hydrate({profile, domId, region, isHidden}) {
|
||||
this.profile = profile;
|
||||
this.domId = domId;
|
||||
this.region = region;
|
||||
this.isHidden = isHidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {{profile: string, domId: string, region: string, isHidden: number}}
|
||||
*/
|
||||
dehydrate() {
|
||||
return {
|
||||
profile: this.profile,
|
||||
domId: this.domId,
|
||||
region: this.region,
|
||||
isHidden: Number(this.isHidden)
|
||||
}
|
||||
}
|
||||
}
|
||||
15
assets/js/idb_stores.js
Normal file
15
assets/js/idb_stores.js
Normal file
@ -0,0 +1,15 @@
|
||||
import {Store, Index} from "./Classes/Store";
|
||||
|
||||
|
||||
export const IDB_stores = {
|
||||
ProfileStore: new Store("profile", false, "slug", [
|
||||
new Index("isActive", false)
|
||||
]),
|
||||
RegionStore: new Store("region", false, "slug"),
|
||||
FilterStore: new Store("filter", false, ["region", "slug"], [
|
||||
new Index("region", false)
|
||||
]),
|
||||
NodeStore: new Store("node", false, ["profile", "domId"], [
|
||||
new Index("region", false)
|
||||
]),
|
||||
};
|
||||
1
assets/js/statics.js
Normal file
1
assets/js/statics.js
Normal file
@ -0,0 +1 @@
|
||||
export const STATIC_ENV = "prod";
|
||||
35
assets/js/stores.js
Normal file
35
assets/js/stores.js
Normal file
@ -0,0 +1,35 @@
|
||||
const WorldmapFilterStore = {
|
||||
autoIncrement: false,
|
||||
keyPath: "id",
|
||||
storeName: "worldmapFilter",
|
||||
// __construct: {
|
||||
// id: "",
|
||||
// filters: {},
|
||||
// },
|
||||
_filters: {},
|
||||
storeObjects: {}
|
||||
};
|
||||
|
||||
const WorldmapStore = {
|
||||
autoIncrement: false,
|
||||
keyPath: "id",
|
||||
storeName: "worldmap",
|
||||
_region: {
|
||||
id: "",
|
||||
name: "",
|
||||
scrollLeft: 50,
|
||||
scrollTop: 50,
|
||||
zoomLevel: 1,
|
||||
}
|
||||
};
|
||||
|
||||
// const NodeStore = {
|
||||
// storeName: "node",
|
||||
// keyPath: "id",
|
||||
// autoIncrement: false
|
||||
// }
|
||||
|
||||
export const IDB_stores = {
|
||||
WorldmapFilterStore,
|
||||
WorldmapStore
|
||||
};
|
||||
17
bin/console
Executable file
17
bin/console
Executable file
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
use App\Kernel;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
|
||||
if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
|
||||
throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".');
|
||||
}
|
||||
|
||||
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
|
||||
|
||||
return function (array $context) {
|
||||
$kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||
|
||||
return new Application($kernel);
|
||||
};
|
||||
107
composer.json
Normal file
107
composer.json
Normal file
@ -0,0 +1,107 @@
|
||||
{
|
||||
"type": "project",
|
||||
"license": "proprietary",
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true,
|
||||
"require": {
|
||||
"php": ">=8.4",
|
||||
"ext-ctype": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-imagick": "*",
|
||||
"doctrine/annotations": "^1.0",
|
||||
"doctrine/doctrine-bundle": "^2.5",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.2",
|
||||
"doctrine/orm": "^2.11",
|
||||
"mobiledetect/mobiledetectlib": "^2.8",
|
||||
"phpdocumentor/reflection-docblock": "^5.3",
|
||||
"phpstan/phpdoc-parser": "^1.2",
|
||||
"ramsey/uuid": "^4.2",
|
||||
"sensio/framework-extra-bundle": "^6.1",
|
||||
"symfony/asset": "5.4.*",
|
||||
"symfony/console": "5.4.*",
|
||||
"symfony/doctrine-messenger": "5.4.*",
|
||||
"symfony/dotenv": "5.4.*",
|
||||
"symfony/expression-language": "5.4.*",
|
||||
"symfony/flex": "^1.17|^2",
|
||||
"symfony/form": "5.4.*",
|
||||
"symfony/framework-bundle": "5.4.*",
|
||||
"symfony/http-client": "5.4.*",
|
||||
"symfony/intl": "5.4.*",
|
||||
"symfony/mailer": "5.4.*",
|
||||
"symfony/mime": "5.4.*",
|
||||
"symfony/monolog-bundle": "^3.0",
|
||||
"symfony/notifier": "5.4.*",
|
||||
"symfony/process": "5.4.*",
|
||||
"symfony/property-access": "5.4.*",
|
||||
"symfony/property-info": "5.4.*",
|
||||
"symfony/proxy-manager-bridge": "5.4.*",
|
||||
"symfony/runtime": "5.4.*",
|
||||
"symfony/security-bundle": "5.4.*",
|
||||
"symfony/serializer": "5.4.*",
|
||||
"symfony/string": "5.4.*",
|
||||
"symfony/translation": "5.4.*",
|
||||
"symfony/twig-bundle": "5.4.*",
|
||||
"symfony/validator": "5.4.*",
|
||||
"symfony/web-link": "5.4.*",
|
||||
"symfony/webapp-meta": "^1.0",
|
||||
"symfony/webpack-encore-bundle": "^1.12",
|
||||
"symfony/yaml": "5.4.*",
|
||||
"twig/extra-bundle": "^2.12|^3.0",
|
||||
"twig/twig": "^2.12|^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/debug-bundle": "5.4.*",
|
||||
"symfony/maker-bundle": "^1.0",
|
||||
"symfony/stopwatch": "5.4.*",
|
||||
"symfony/web-profiler-bundle": "5.4.*"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"composer/package-versions-deprecated": true,
|
||||
"symfony/flex": true,
|
||||
"symfony/runtime": true
|
||||
},
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": {
|
||||
"*": "dist"
|
||||
},
|
||||
"sort-packages": true
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"App\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"replace": {
|
||||
"symfony/polyfill-ctype": "*",
|
||||
"symfony/polyfill-iconv": "*",
|
||||
"symfony/polyfill-php72": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"auto-scripts": {
|
||||
"cache:clear": "symfony-cmd",
|
||||
"assets:install %PUBLIC_DIR%": "symfony-cmd"
|
||||
},
|
||||
"post-install-cmd": [
|
||||
"@auto-scripts"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"@auto-scripts"
|
||||
]
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/symfony": "*"
|
||||
},
|
||||
"extra": {
|
||||
"symfony": {
|
||||
"allow-contrib": false,
|
||||
"require": "5.4.*",
|
||||
"docker": false
|
||||
}
|
||||
}
|
||||
}
|
||||
8809
composer.lock
generated
Normal file
8809
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
16
config/bundles.php
Normal file
16
config/bundles.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
|
||||
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
|
||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
||||
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
|
||||
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
||||
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
|
||||
];
|
||||
19
config/packages/cache.yaml
Normal file
19
config/packages/cache.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
framework:
|
||||
cache:
|
||||
# Unique name of your app: used to compute stable namespaces for cache keys.
|
||||
#prefix_seed: your_vendor_name/app_name
|
||||
|
||||
# The "app" cache stores to the filesystem by default.
|
||||
# The data in this cache should persist between deploys.
|
||||
# Other options include:
|
||||
|
||||
# Redis
|
||||
#app: cache.adapter.redis
|
||||
#default_redis_provider: redis://localhost
|
||||
|
||||
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
|
||||
#app: cache.adapter.apcu
|
||||
|
||||
# Namespaced pools use the above "app" backend by default
|
||||
#pools:
|
||||
#my.dedicated.cache: null
|
||||
5
config/packages/debug.yaml
Normal file
5
config/packages/debug.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
when@dev:
|
||||
debug:
|
||||
# Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser.
|
||||
# See the "server:dump" command to start a new server.
|
||||
dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%"
|
||||
47
config/packages/doctrine.yaml
Normal file
47
config/packages/doctrine.yaml
Normal file
@ -0,0 +1,47 @@
|
||||
doctrine:
|
||||
dbal:
|
||||
url: '%env(resolve:DATABASE_URL)%'
|
||||
# server_version: '8.0'
|
||||
types:
|
||||
tinyint: 'App\Doctrine\DBAL\Types\TinyintType'
|
||||
mapping_types:
|
||||
tinyiny: 'tinyint'
|
||||
|
||||
# IMPORTANT: You MUST configure your server version,
|
||||
# either here or in the DATABASE_URL env var (see .env file)
|
||||
#server_version: '13'
|
||||
orm:
|
||||
auto_generate_proxy_classes: true
|
||||
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
||||
auto_mapping: true
|
||||
mappings:
|
||||
App:
|
||||
is_bundle: false
|
||||
dir: '%kernel.project_dir%/src/Entity'
|
||||
prefix: 'App\Entity'
|
||||
alias: App
|
||||
|
||||
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
|
||||
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
config/packages/doctrine_migrations.yaml
Normal file
6
config/packages/doctrine_migrations.yaml
Normal 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: '%kernel.debug%'
|
||||
24
config/packages/framework.yaml
Normal file
24
config/packages/framework.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
# see https://symfony.com/doc/current/reference/configuration/framework.html
|
||||
framework:
|
||||
secret: '%env(APP_SECRET)%'
|
||||
#csrf_protection: true
|
||||
http_method_override: false
|
||||
|
||||
# Enables session support. Note that the session will ONLY be started if you read or write from it.
|
||||
# Remove or comment this section to explicitly disable session support.
|
||||
session:
|
||||
handler_id: null
|
||||
cookie_secure: auto
|
||||
cookie_samesite: lax
|
||||
storage_factory_id: session.storage.factory.native
|
||||
|
||||
#esi: true
|
||||
#fragments: true
|
||||
php_errors:
|
||||
log: true
|
||||
|
||||
when@test:
|
||||
framework:
|
||||
test: true
|
||||
session:
|
||||
storage_factory_id: session.storage.factory.mock_file
|
||||
3
config/packages/mailer.yaml
Normal file
3
config/packages/mailer.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
framework:
|
||||
mailer:
|
||||
dsn: '%env(MAILER_DSN)%'
|
||||
25
config/packages/messenger.yaml
Normal file
25
config/packages/messenger.yaml
Normal file
@ -0,0 +1,25 @@
|
||||
framework:
|
||||
messenger:
|
||||
failure_transport: failed
|
||||
reset_on_message: true
|
||||
|
||||
transports:
|
||||
# https://symfony.com/doc/current/messenger.html#transport-configuration
|
||||
async:
|
||||
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
|
||||
options:
|
||||
use_notify: true
|
||||
check_delayed_interval: 60000
|
||||
retry_strategy:
|
||||
max_retries: 3
|
||||
multiplier: 2
|
||||
failed: 'doctrine://default?queue_name=failed'
|
||||
# sync: 'sync://'
|
||||
|
||||
routing:
|
||||
Symfony\Component\Mailer\Messenger\SendEmailMessage: async
|
||||
Symfony\Component\Notifier\Message\ChatMessage: async
|
||||
Symfony\Component\Notifier\Message\SmsMessage: async
|
||||
|
||||
# Route your messages to the transports
|
||||
# 'App\Message\YourMessage': async
|
||||
61
config/packages/monolog.yaml
Normal file
61
config/packages/monolog.yaml
Normal file
@ -0,0 +1,61 @@
|
||||
monolog:
|
||||
channels:
|
||||
- deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
|
||||
|
||||
when@dev:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
channels: ["!event"]
|
||||
# uncomment to get logging in your browser
|
||||
# you may have to allow bigger header sizes in your Web server configuration
|
||||
#firephp:
|
||||
# type: firephp
|
||||
# level: info
|
||||
#chromephp:
|
||||
# type: chromephp
|
||||
# level: info
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine", "!console"]
|
||||
|
||||
when@test:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: fingers_crossed
|
||||
action_level: error
|
||||
handler: nested
|
||||
excluded_http_codes: [404, 405]
|
||||
channels: ["!event"]
|
||||
nested:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
|
||||
when@prod:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: fingers_crossed
|
||||
action_level: error
|
||||
handler: nested
|
||||
excluded_http_codes: [404, 405]
|
||||
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
|
||||
nested:
|
||||
type: stream
|
||||
path: php://stderr
|
||||
level: debug
|
||||
formatter: monolog.formatter.json
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine"]
|
||||
deprecation:
|
||||
type: stream
|
||||
channels: [deprecation]
|
||||
path: php://stderr
|
||||
16
config/packages/notifier.yaml
Normal file
16
config/packages/notifier.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
framework:
|
||||
notifier:
|
||||
#chatter_transports:
|
||||
# slack: '%env(SLACK_DSN)%'
|
||||
# telegram: '%env(TELEGRAM_DSN)%'
|
||||
#texter_transports:
|
||||
# twilio: '%env(TWILIO_DSN)%'
|
||||
# nexmo: '%env(NEXMO_DSN)%'
|
||||
channel_policy:
|
||||
# use chat/slack, chat/telegram, sms/twilio or sms/nexmo
|
||||
urgent: ['email']
|
||||
high: ['email']
|
||||
medium: ['email']
|
||||
low: ['email']
|
||||
admin_recipients:
|
||||
- { email: admin@example.com }
|
||||
12
config/packages/routing.yaml
Normal file
12
config/packages/routing.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
framework:
|
||||
router:
|
||||
utf8: true
|
||||
|
||||
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
|
||||
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
|
||||
#default_uri: http://localhost
|
||||
|
||||
when@prod:
|
||||
framework:
|
||||
router:
|
||||
strict_requirements: null
|
||||
63
config/packages/security.yaml
Normal file
63
config/packages/security.yaml
Normal file
@ -0,0 +1,63 @@
|
||||
security:
|
||||
enable_authenticator_manager: true
|
||||
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
|
||||
password_hashers:
|
||||
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
|
||||
App\Entity\User:
|
||||
algorithm: auto
|
||||
|
||||
role_hierarchy:
|
||||
ROLE_USER: [ ]
|
||||
ROLE_CONTRIBUTOR: [ ]
|
||||
ROLE_SENIOR: [ ROLE_CONTRIBUTOR ]
|
||||
ROLE_CBT: [ ]
|
||||
ROLE_ADMIN: [ ROLE_SENIOR ]
|
||||
|
||||
# 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
|
||||
custom_authenticator: App\Security\Authenticator
|
||||
remember_me:
|
||||
secret: '%kernel.secret%'
|
||||
lifetime: 2592000
|
||||
always_remember_me: true
|
||||
logout:
|
||||
path: security_logout
|
||||
# where to redirect after logout
|
||||
# target: app_any_route
|
||||
|
||||
# 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
|
||||
3
config/packages/sensio_framework_extra.yaml
Normal file
3
config/packages/sensio_framework_extra.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
sensio_framework_extra:
|
||||
router:
|
||||
annotations: false
|
||||
13
config/packages/translation.yaml
Normal file
13
config/packages/translation.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
framework:
|
||||
default_locale: '%locale%'
|
||||
translator:
|
||||
default_path: '%kernel.project_dir%/translations'
|
||||
fallbacks:
|
||||
- '%locale%'
|
||||
# providers:
|
||||
# crowdin:
|
||||
# dsn: '%env(CROWDIN_DSN)%'
|
||||
# loco:
|
||||
# dsn: '%env(LOCO_DSN)%'
|
||||
# lokalise:
|
||||
# dsn: '%env(LOKALISE_DSN)%'
|
||||
39
config/packages/twig.yaml
Normal file
39
config/packages/twig.yaml
Normal file
@ -0,0 +1,39 @@
|
||||
twig:
|
||||
default_path: '%kernel.project_dir%/templates'
|
||||
globals:
|
||||
assets:
|
||||
img:
|
||||
_black: '/build/assets/static/_black.png'
|
||||
_black_xs: '/build/assets/static/_black_xs.png'
|
||||
_blank: '/build/assets/static/_blank.png'
|
||||
_blank_xs: '/build/assets/static/_blank_xs.png'
|
||||
delete: '/build/assets/static/delete.png'
|
||||
region: '/build/assets/static/region/'
|
||||
ui: '/build/assets/static/ui/'
|
||||
map:
|
||||
ext: ['jpg', 'jpeg']
|
||||
sand: '/build/assets/static/map/sand.jpg'
|
||||
sea: '/build/assets/static/map/sea.jpg'
|
||||
upload_path: '/upload/map/'
|
||||
item:
|
||||
ext: ['png']
|
||||
upload_path: '/upload/item/'
|
||||
monster:
|
||||
ext: ['png']
|
||||
upload_path: '/upload/monster/'
|
||||
screenshot:
|
||||
ext: ['jpg', 'jpeg', 'png']
|
||||
upload_path: '/upload/screenshot/'
|
||||
thumbnail_path: '/upload/screenshot/thumbnail/'
|
||||
worldmark:
|
||||
ext: ['png']
|
||||
upload_path: '/upload/worldmark/'
|
||||
upload:
|
||||
map:
|
||||
ext: ['jpg', 'jpeg']
|
||||
path: '/upload/map/'
|
||||
thumbnail: '/upload/map/thumbnail/'
|
||||
|
||||
when@test:
|
||||
twig:
|
||||
strict_variables: true
|
||||
13
config/packages/validator.yaml
Normal file
13
config/packages/validator.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
framework:
|
||||
validation:
|
||||
email_validation_mode: html5
|
||||
|
||||
# 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
|
||||
15
config/packages/web_profiler.yaml
Normal file
15
config/packages/web_profiler.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
when@dev:
|
||||
web_profiler:
|
||||
toolbar: true
|
||||
intercept_redirects: false
|
||||
|
||||
framework:
|
||||
profiler: { only_exceptions: false }
|
||||
|
||||
when@test:
|
||||
web_profiler:
|
||||
toolbar: false
|
||||
intercept_redirects: false
|
||||
|
||||
framework:
|
||||
profiler: { collect: false }
|
||||
49
config/packages/webpack_encore.yaml
Normal file
49
config/packages/webpack_encore.yaml
Normal file
@ -0,0 +1,49 @@
|
||||
webpack_encore:
|
||||
# The path where Encore is building the assets - i.e. Encore.setOutputPath()
|
||||
output_path: '%kernel.project_dir%/public/build'
|
||||
# If multiple builds are defined (as shown below), you can disable the default build:
|
||||
# output_path: false
|
||||
|
||||
# Set attributes that will be rendered on all script and link tags
|
||||
script_attributes:
|
||||
defer: true
|
||||
# Uncomment (also under link_attributes) if using Turbo Drive
|
||||
# https://turbo.hotwired.dev/handbook/drive#reloading-when-assets-change
|
||||
# 'data-turbo-track': reload
|
||||
# link_attributes:
|
||||
# Uncomment if using Turbo Drive
|
||||
# 'data-turbo-track': reload
|
||||
|
||||
# If using Encore.enableIntegrityHashes() and need the crossorigin attribute (default: false, or use 'anonymous' or 'use-credentials')
|
||||
# crossorigin: 'anonymous'
|
||||
|
||||
# Preload all rendered script and link tags automatically via the HTTP/2 Link header
|
||||
# preload: true
|
||||
|
||||
# Throw an exception if the entrypoints.json file is missing or an entry is missing from the data
|
||||
# strict_mode: false
|
||||
|
||||
# If you have multiple builds:
|
||||
# builds:
|
||||
# pass "frontend" as the 3rg arg to the Twig functions
|
||||
# {{ encore_entry_script_tags('entry1', null, 'frontend') }}
|
||||
|
||||
# frontend: '%kernel.project_dir%/public/frontend/build'
|
||||
|
||||
# Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes)
|
||||
# Put in config/packages/prod/webpack_encore.yaml
|
||||
# cache: true
|
||||
|
||||
framework:
|
||||
assets:
|
||||
json_manifest_path: '%kernel.project_dir%/public/build/manifest.json'
|
||||
|
||||
#when@prod:
|
||||
# webpack_encore:
|
||||
# # Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes)
|
||||
# # Available in version 1.2
|
||||
# cache: true
|
||||
|
||||
#when@test:
|
||||
# webpack_encore:
|
||||
# strict_mode: false
|
||||
5
config/preload.php
Normal file
5
config/preload.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) {
|
||||
require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php';
|
||||
}
|
||||
11
config/routes.yaml
Normal file
11
config/routes.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
index:
|
||||
# path: /{_locale}
|
||||
path: /
|
||||
controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction
|
||||
# requirements:
|
||||
# _locale: '%locales%'
|
||||
defaults:
|
||||
route: fo_region_show
|
||||
slug: 'mondstadt'
|
||||
permanent: true
|
||||
# _locale: '%locale%'
|
||||
7
config/routes/annotations.yaml
Normal file
7
config/routes/annotations.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
controllers:
|
||||
resource: ../../src/Controller/
|
||||
type: annotation
|
||||
|
||||
kernel:
|
||||
resource: ../../src/Kernel.php
|
||||
type: annotation
|
||||
4
config/routes/framework.yaml
Normal file
4
config/routes/framework.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
when@dev:
|
||||
_errors:
|
||||
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
|
||||
prefix: /_error
|
||||
8
config/routes/web_profiler.yaml
Normal file
8
config/routes/web_profiler.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
when@dev:
|
||||
web_profiler_wdt:
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
|
||||
prefix: /dev/_wdt
|
||||
|
||||
web_profiler_profiler:
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
|
||||
prefix: /dev/_profiler
|
||||
68
config/services.yaml
Normal file
68
config/services.yaml
Normal file
@ -0,0 +1,68 @@
|
||||
# This file is the entry point to configure your own services.
|
||||
# Files in the packages/ subdirectory configure your dependencies.
|
||||
|
||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
|
||||
parameters:
|
||||
locale: 'en'
|
||||
supported_locales: [ 'en', 'fr' ]
|
||||
assets:
|
||||
img:
|
||||
region: '%kernel.project_dir%/public/build/assets/static/region'
|
||||
ui: '%kernel.project_dir%/public/build/assets/static/ui'
|
||||
map:
|
||||
ext: ['jpg', 'jpeg']
|
||||
sand: '%kernel.project_dir%/public/build/assets/static/map/sand.jpg'
|
||||
sea: '%kernel.project_dir%/public/build/assets/static/map/sea.jpg'
|
||||
upload_path: '%kernel.project_dir%/public/upload/map'
|
||||
item:
|
||||
ext: ['png']
|
||||
upload_path: '%kernel.project_dir%/public/upload/item'
|
||||
monster:
|
||||
ext: [ 'png' ]
|
||||
upload_path: '%kernel.project_dir%/public/upload/monster'
|
||||
screenshot:
|
||||
ext: [ 'jpg', 'jpeg', 'png' ]
|
||||
upload_path: '%kernel.project_dir%/public/upload/screenshot'
|
||||
thumbnail_path: '%kernel.project_dir%/public/upload/screenshot/thumbnail'
|
||||
worldmark:
|
||||
ext: [ 'png' ]
|
||||
upload_path: '%kernel.project_dir%/public/upload/worldmark'
|
||||
upload:
|
||||
map:
|
||||
ext: ['jpg', 'jpeg']
|
||||
path: '%kernel.project_dir%/public/upload/map'
|
||||
thumbnail: '%kernel.project_dir%/public/upload/map/thumbnail'
|
||||
|
||||
services:
|
||||
# default configuration for services in *this* file
|
||||
_defaults:
|
||||
autowire: true # Automatically injects dependencies in your services.
|
||||
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||
|
||||
# makes classes in src/ available to be used as services
|
||||
# this creates a service per class whose id is the fully-qualified class name
|
||||
App\:
|
||||
resource: '../src/'
|
||||
exclude:
|
||||
- '../src/DependencyInjection/'
|
||||
- '../src/Entity/'
|
||||
- '../src/Kernel.php'
|
||||
- '../src/Tests/'
|
||||
|
||||
# controllers are imported separately to make sure services can be injected
|
||||
# as action arguments even if you don't extend any base controller class
|
||||
App\Controller\:
|
||||
resource: '../src/Controller/'
|
||||
tags: ['controller.service_arguments']
|
||||
|
||||
# Detection\MobileDetect: []
|
||||
|
||||
# add more service definitions when explicit configuration is needed
|
||||
# please note that last definitions always *replace* previous ones
|
||||
App\EventListener\KernelListener:
|
||||
tags:
|
||||
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
|
||||
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
|
||||
- { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }
|
||||
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
|
||||
0
migrations/.gitignore
vendored
Normal file
0
migrations/.gitignore
vendored
Normal file
21
package.json
Normal file
21
package.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"@hotwired/stimulus": "^3.0.0",
|
||||
"@symfony/stimulus-bridge": "^3.0.0",
|
||||
"@symfony/webpack-encore": "^1.7.0",
|
||||
"core-js": "^3.0.0",
|
||||
"regenerator-runtime": "^0.13.2",
|
||||
"sass": "^1.49.9",
|
||||
"sass-loader": "^12.6.0",
|
||||
"webpack-notifier": "^1.6.0"
|
||||
},
|
||||
"license": "UNLICENSED",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev-server": "encore dev-server",
|
||||
"dev": "encore dev",
|
||||
"watch": "encore dev --watch",
|
||||
"build": "encore production --progress"
|
||||
},
|
||||
"packageManager": "yarn@4.6.0+sha512.5383cc12567a95f1d668fbe762dfe0075c595b4bfff433be478dbbe24e05251a8e8c3eb992a986667c1d53b6c3a9c85b8398c35a960587fbd9fa3a0915406728"
|
||||
}
|
||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
9
public/index.php
Normal file
9
public/index.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
use App\Kernel;
|
||||
|
||||
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
|
||||
|
||||
return function (array $context) {
|
||||
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||
};
|
||||
BIN
public/og.jpg
Normal file
BIN
public/og.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 372 KiB |
4
public/robots.txt
Normal file
4
public/robots.txt
Normal file
@ -0,0 +1,4 @@
|
||||
sitemap: https://genshin-world.com/sitemap.xml
|
||||
|
||||
User-agent: *
|
||||
Disallow: /7f447c48
|
||||
58
public/sitemap.xml
Normal file
58
public/sitemap.xml
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
|
||||
<url>
|
||||
<loc>https://genshin-world.com/mondstadt</loc>
|
||||
<lastmod>2022-09-28T00:00:00+00:00</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.80</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://genshin-world.com/dragonspine</loc>
|
||||
<lastmod>2022-09-28T00:00:00+00:00</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.80</priority>
|
||||
</url>
|
||||
<!--<url>-->
|
||||
<!-- <loc>https://genshin-world.com/golden-apple-archipelago</loc>-->
|
||||
<!-- <lastmod>2022-09-28T00:00:00+00:00</lastmod>-->
|
||||
<!-- <changefreq>weekly</changefreq>-->
|
||||
<!-- <priority>0.90</priority>-->
|
||||
<!--</url>-->
|
||||
<url>
|
||||
<loc>https://genshin-world.com/liyue</loc>
|
||||
<lastmod>2022-09-28T00:00:00+00:00</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.80</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://genshin-world.com/the-chasm</loc>
|
||||
<lastmod>2022-09-28T00:00:00+00:00</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.80</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://genshin-world.com/underground-mines</loc>
|
||||
<lastmod>2022-09-28T00:00:00+00:00</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.90</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://genshin-world.com/inazuma</loc>
|
||||
<lastmod>2022-09-28T00:00:00+00:00</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.80</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://genshin-world.com/enkanomiya</loc>
|
||||
<lastmod>2022-09-28T00:00:00+00:00</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.80</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://genshin-world.com/sumeru</loc>
|
||||
<lastmod>2022-09-28T00:00:00+00:00</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.00</priority>
|
||||
</url>
|
||||
</urlset>
|
||||
0
src/Controller/.gitignore
vendored
Normal file
0
src/Controller/.gitignore
vendored
Normal file
19
src/Controller/DefaultController.php
Normal file
19
src/Controller/DefaultController.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class DefaultController extends AbstractController {
|
||||
#[Route('/dashboard', name: 'bo_dashboard', methods: ['GET'])]
|
||||
public function dashboard(): Response {
|
||||
return $this->render('_dashboard/base.html.twig');
|
||||
}
|
||||
|
||||
// #[Route('/sandbox', name: 'sandbox', methods: 'GET')]
|
||||
// public function sandbox(): Response {
|
||||
// return $this->render('sandbox/sandbox.html.twig');
|
||||
// }
|
||||
}
|
||||
128
src/Controller/GridController.php
Normal file
128
src/Controller/GridController.php
Normal file
@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Grid;
|
||||
use App\Entity\Region;
|
||||
use App\Kernel;
|
||||
use App\Repository\GridRepository;
|
||||
use App\Repository\MapRepository;
|
||||
use App\Service\FileManager;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route('/dashboard/regions/region-{regionId}/grid')]
|
||||
#[ParamConverter(data: 'region', class: Region::class, options: ['id' => 'regionId'])]
|
||||
class GridController extends AbstractController {
|
||||
public function __construct(private EntityManagerInterface $_em,
|
||||
private FileManager $fileManager,
|
||||
private GridRepository $gridRepository,
|
||||
private MapRepository $mapRepository) {}
|
||||
|
||||
#[Route('', name: 'bo_region_grid_index', methods: ['GET'])]
|
||||
public function index(Request $request, Region $region): Response {
|
||||
$version = $request->query->get('v');
|
||||
$version = !$version || !in_array(floatval($version), Kernel::SUPPORTED_GAME_VERSION) ? Kernel::GAME_VERSION : floatval($version);
|
||||
|
||||
$cells = $this->gridRepository->getGridCells($region);
|
||||
$maps = $this->mapRepository->getCellsMap($cells, $version);
|
||||
$grid = $this->gridRepository->buildWorldmap($version, $cells, $maps, true);
|
||||
|
||||
return $this->render('_dashboard/grid/index.html.twig', array(
|
||||
'region' => $region,
|
||||
'grid' => $grid,
|
||||
'version' => $version,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/edit', name: 'bo_region_grid_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, Region $region): Response {
|
||||
$logs=array();
|
||||
$form = $this->gridRepository->getGridForm('bo_region_grid_edit', $region);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted() && $form->isValid()) {
|
||||
if(is_array($form->get('positions')->getData())) {
|
||||
if(in_array('row_before', $form->get('positions')->getData())) {
|
||||
$this->addRow($region, $this->gridRepository->getGridCells($region), true);
|
||||
$logs[]='• Added one row before.';
|
||||
}
|
||||
|
||||
if(in_array('row_after', $form->get('positions')->getData())) {
|
||||
$this->addRow($region, $this->gridRepository->getGridCells($region), false);
|
||||
$logs[]='• Added one row after.';
|
||||
}
|
||||
|
||||
if(in_array('column_before', $form->get('positions')->getData())) {
|
||||
$this->addColumn($region, $this->gridRepository->getGridCells($region), true);
|
||||
$logs[]='• Added one column before.';
|
||||
}
|
||||
|
||||
if(in_array('column_after', $form->get('positions')->getData())) {
|
||||
$this->addColumn($region, $this->gridRepository->getGridCells($region), false);
|
||||
$logs[]='• Added one column after.';
|
||||
}
|
||||
|
||||
$form = $this->gridRepository->getGridForm('bo_region_grid_edit', $region);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->renderForm('_dashboard/grid/edit.html.twig', array(
|
||||
'region' => $region,
|
||||
'form' => $form,
|
||||
'logs' => $logs,
|
||||
));
|
||||
}
|
||||
|
||||
private function addColumn(Region $region, array $cells, bool $isBefore) {
|
||||
if($isBefore) {
|
||||
foreach($cells as $_cell) {
|
||||
$_cell->setCol($_cell->getCol() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
for($n = 1; $n <= $region->getGridHeight(); $n++) {
|
||||
$cell = new Grid();
|
||||
$cell->setRegion($region)
|
||||
->setCol($isBefore ? 1 : $region->getGridWidth() + 1)
|
||||
->setRow($n);
|
||||
|
||||
$this->_em->persist($cell);
|
||||
}
|
||||
|
||||
$region->setGridWidth($region->getGridWidth() + 1);
|
||||
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Region $region
|
||||
* @param Grid[] $cells
|
||||
* @param bool $isBefore
|
||||
* @return void
|
||||
*/
|
||||
private function addRow(Region $region, array $cells, bool $isBefore) {
|
||||
if($isBefore) {
|
||||
foreach($cells as $_cell) {
|
||||
$_cell->setRow($_cell->getRow() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
for($n = 1; $n <= $region->getGridWidth(); $n++) {
|
||||
$cell = new Grid();
|
||||
$cell->setRegion($region)
|
||||
->setCol($n)
|
||||
->setRow($isBefore ? 1 : $region->getGridHeight() + 1);
|
||||
|
||||
$this->_em->persist($cell);
|
||||
}
|
||||
|
||||
$region->setGridHeight($region->getGridHeight() + 1);
|
||||
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
88
src/Controller/ItemCategoryController.php
Normal file
88
src/Controller/ItemCategoryController.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\ItemCategory;
|
||||
use App\Form\ItemCategoryType;
|
||||
use App\Repository\ItemCategoryRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route('/dashboard/items-categories')]
|
||||
class ItemCategoryController extends AbstractController {
|
||||
public function __construct(private EntityManagerInterface $_em,
|
||||
private ItemCategoryRepository $itemCategoryRepository) {}
|
||||
|
||||
#[Route('', name: 'bo_item_category_index', methods: ['GET'])]
|
||||
public function index(): Response {
|
||||
$itemsCategories = $this->itemCategoryRepository->findBy(array(), array('sortOrder' => 'ASC'));
|
||||
|
||||
return $this->render('_dashboard/item_category/index.html.twig', array(
|
||||
'itemsCategories' => $itemsCategories,
|
||||
));
|
||||
}
|
||||
|
||||
//ToDo set form to XHR for errors
|
||||
#[Route('/new', name: 'bo_item_category_new', methods: ['GET', 'POST'])]
|
||||
public function new(Request $request): Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
$itemCategory = new ItemCategory();
|
||||
$form = $this->itemCategoryRepository->getForm('bo_item_category_new', $itemCategory);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted() && $form->isValid()) {
|
||||
$this->_em->persist($itemCategory);
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->redirectToRoute('bo_item_category_index', array(), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
|
||||
$itemsCategories=$this->itemCategoryRepository->findBy(array(), array('sortOrder'=>'ASC'));
|
||||
|
||||
return $this->renderForm('_dashboard/item_category/new.html.twig', array(
|
||||
'itemsCategories'=>$itemsCategories,
|
||||
'itemCategory'=>$itemCategory,
|
||||
'form'=>$form,
|
||||
));
|
||||
}
|
||||
|
||||
//ToDo set form to XHR for errors
|
||||
#[Route('/category-{id}', name: 'bo_item_category_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, ItemCategory $itemCategory): Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
$form = $this->itemCategoryRepository->getForm('bo_item_category_edit', $itemCategory);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted() && $form->isValid()) {
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->redirectToRoute('bo_item_category_index', array(), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
|
||||
$itemsCategories=$this->itemCategoryRepository->findBy(array(), array('sortOrder'=>'ASC'));
|
||||
|
||||
return $this->renderForm('_dashboard/item_category/edit.html.twig', [
|
||||
'itemsCategories'=>$itemsCategories,
|
||||
'itemCategory'=>$itemCategory,
|
||||
'form'=>$form,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/delete-{id}', name: 'bo_item_category_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, ItemCategory $itemCategory): RedirectResponse {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
if($this->isCsrfTokenValid('delete'.$itemCategory->getId(), $request->request->get('_token'))) {
|
||||
$this->_em->remove($itemCategory);
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
return $this->redirectToRoute('bo_item_category_index', array(), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
}
|
||||
239
src/Controller/ItemController.php
Normal file
239
src/Controller/ItemController.php
Normal file
@ -0,0 +1,239 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Item;
|
||||
use App\Entity\ItemCategory;
|
||||
use App\Repository\ItemCategoryRepository;
|
||||
use App\Repository\ItemRepository;
|
||||
use App\Repository\WorldmarkRepository;
|
||||
use App\Service\FileManager;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route('/dashboard/items-categories/category-{itemCategoryId}/items')]
|
||||
#[ParamConverter(data: 'itemCategory', class: ItemCategory::class, options: ['id' => 'itemCategoryId'])]
|
||||
class ItemController extends AbstractController {
|
||||
public function __construct(private EntityManagerInterface $_em,
|
||||
private FileManager $fileManager,
|
||||
private ItemCategoryRepository $itemCategoryRepository,
|
||||
private ItemRepository $itemRepository) {}
|
||||
|
||||
#[Route('', name: 'bo_item_index', methods: ['GET'])]
|
||||
public function index(ItemCategory $itemCategory): Response {
|
||||
$itemsCategories=$this->itemCategoryRepository->findBy(array(), array('sortOrder'=>'ASC'));
|
||||
$items=$this->itemRepository->findBy(array('category'=>$itemCategory), array('name'=>'ASC'));
|
||||
|
||||
return $this->render('_dashboard/item/index.html.twig', array(
|
||||
'itemsCategories'=>$itemsCategories,
|
||||
'itemCategory'=>$itemCategory,
|
||||
'items'=>$items,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/new', name: 'bo_item_new', methods: ['GET', 'POST'])]
|
||||
public function new(Request $request, ItemCategory $itemCategory): Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_SENIOR');
|
||||
|
||||
if($request->isMethod('POST') && !$request->isXmlHttpRequest()) {
|
||||
throw new NotFoundHttpException("Page not found");
|
||||
}
|
||||
|
||||
$item=new Item();
|
||||
$item->setCategory($itemCategory);
|
||||
|
||||
$form=$this->itemRepository->getForm('bo_item_new', $itemCategory, $item);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted()) {
|
||||
if($form->isValid()) {
|
||||
if($item->getIcon() instanceof UploadedFile) {
|
||||
$uploadedFile=$this->fileManager->uploadItemIcon($item->getIcon());
|
||||
|
||||
if($uploadedFile['error']) {
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => $uploadedFile['message'],
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
$item->setIcon($uploadedFile['filename']);
|
||||
}
|
||||
|
||||
$this->_em->persist($item);
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'redirect',
|
||||
'params' => array(
|
||||
'url' => $this->generateUrl('bo_item_index', array('itemCategoryId' => $itemCategory->getId())),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'Invalid form',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
$itemsCategories=$this->itemCategoryRepository->findBy(array(), array('sortOrder'=>'ASC'));
|
||||
|
||||
return $this->renderForm('_dashboard/item/new.html.twig', array(
|
||||
'itemsCategories'=>$itemsCategories,
|
||||
'itemCategory'=>$itemCategory,
|
||||
'item'=>$item,
|
||||
'form'=>$form,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/item-{id}', name: 'bo_item_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, WorldmarkRepository $worldmarkRepository, ItemCategory $itemCategory, Item $item): Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_SENIOR');
|
||||
|
||||
if($request->isMethod('POST') && !$request->isXmlHttpRequest()) {
|
||||
throw new NotFoundHttpException("Page not found");
|
||||
}
|
||||
|
||||
$icon=$item->getIcon();
|
||||
|
||||
$form=$this->itemRepository->getForm('bo_item_edit', $itemCategory, $item);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted()) {
|
||||
if($form->isValid()) {
|
||||
if(!$form->get('removeFile')->getData()) {
|
||||
if($item->getIcon() instanceof UploadedFile) {
|
||||
$uploadedFile=$this->fileManager->uploadItemIcon($item->getIcon());
|
||||
|
||||
if($uploadedFile['error']) {
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => $uploadedFile['message'],
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
if($icon) {
|
||||
$this->fileManager->removeItemIcon($icon);
|
||||
}
|
||||
|
||||
$item->setIcon($uploadedFile['filename']);
|
||||
$worldmark = $worldmarkRepository->findOneBy(array('item'=>$item));
|
||||
|
||||
if($worldmark) {
|
||||
$uploadedFile=$this->fileManager->getWorldmarkIconFromEntity($item);
|
||||
|
||||
if($uploadedFile['error']) {
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => $uploadedFile['message'],
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
if($worldmark->getIcon()) {
|
||||
$this->fileManager->removeWorldmarkIcon($icon);
|
||||
}
|
||||
|
||||
$worldmark->setIcon($uploadedFile['filename']);
|
||||
}
|
||||
} else {
|
||||
$item->setIcon($icon);
|
||||
}
|
||||
} else {
|
||||
$this->fileManager->removeItemIcon($icon);
|
||||
|
||||
$item->setIcon(null);
|
||||
}
|
||||
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'redirect',
|
||||
'params' => array(
|
||||
'url' => $this->generateUrl('bo_item_index', array('itemCategoryId' => $itemCategory->getId())),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'Invalid form',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
$itemsCategories=$this->itemCategoryRepository->findBy(array(), array('sortOrder'=>'ASC'));
|
||||
|
||||
return $this->renderForm('_dashboard/item/edit.html.twig', [
|
||||
'itemsCategories'=>$itemsCategories,
|
||||
'itemCategory'=>$itemCategory,
|
||||
'item'=>$item,
|
||||
'form'=>$form,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/delete-{id}', name: 'bo_item_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, ItemCategory $itemCategory, Item $item): RedirectResponse {
|
||||
$this->denyAccessUnlessGranted('ROLE_SENIOR');
|
||||
|
||||
if($this->isCsrfTokenValid('delete'.$item->getId(), $request->request->get('_token'))) {
|
||||
if($item->getIcon()) {
|
||||
$this->fileManager->removeItemIcon($item->getIcon());
|
||||
}
|
||||
|
||||
$this->_em->remove($item);
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
return $this->redirectToRoute('bo_item_index', array('itemCategoryId'=>$itemCategory->getId()), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
}
|
||||
198
src/Controller/MapController.php
Normal file
198
src/Controller/MapController.php
Normal file
@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Grid;
|
||||
use App\Entity\Map;
|
||||
use App\Repository\MapRepository;
|
||||
use App\Service\FileManager;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route('/dashboard/grid/cell-{cellId}/maps')]
|
||||
#[ParamConverter(data: 'cell', class: Grid::class, options: ['id' => 'cellId'])]
|
||||
class MapController extends AbstractController {
|
||||
public function __construct(private EntityManagerInterface $_em,
|
||||
private FileManager $fileManager,
|
||||
private MapRepository $mapRepository) {}
|
||||
|
||||
#[Route('/new', name: 'bo_map_new', methods: ['POST'])]
|
||||
public function new(Request $request, Grid $cell): JsonResponse {
|
||||
if($request->isXmlHttpRequest()) {
|
||||
$map = new Map();
|
||||
$map->setGrid($cell);
|
||||
|
||||
$form = $this->mapRepository->getForm('bo_map_new', $cell, $map);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted()) {
|
||||
if($form->isValid()) {
|
||||
if($map->getFile() instanceof UploadedFile) {
|
||||
$uploadedFile = $this->fileManager->uploadMapFile($map->getFile());
|
||||
|
||||
if($uploadedFile['error']) {
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => $uploadedFile['message'],
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
$map->setFile($uploadedFile['filename']);
|
||||
|
||||
$this->_em->persist($map);
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'success',
|
||||
'message' => 'Map updated',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'No file found or uploaded',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'Invalid form',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'No form submitted',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
#[Route('/map-{id}', name: 'bo_map_edit', methods: ['POST'])]
|
||||
public function edit(Request $request, Grid $cell, Map $map): JsonResponse {
|
||||
if($request->isXmlHttpRequest()) {
|
||||
$file = $map->getFile();
|
||||
|
||||
$form = $this->mapRepository->getForm('bo_map_edit', $cell, $map);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted()) {
|
||||
if($form->isValid()) {
|
||||
if($map->getFile() instanceof UploadedFile) {
|
||||
$uploadedFile=$this->fileManager->uploadMapFile($map->getFile());
|
||||
|
||||
if($uploadedFile['error']) {
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => $uploadedFile['message'],
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
$map->setFile($uploadedFile['filename']);
|
||||
$this->fileManager->removeMapFile($file);
|
||||
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'success',
|
||||
'message' => 'Map updated',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'No file found or uploaded',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'Invalid form',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'No form submitted',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
}
|
||||
85
src/Controller/MonsterCategoryController.php
Normal file
85
src/Controller/MonsterCategoryController.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\MonsterCategory;
|
||||
use App\Repository\MonsterCategoryRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route('/dashboard/monsters-categories')]
|
||||
class MonsterCategoryController extends AbstractController {
|
||||
public function __construct(private EntityManagerInterface $_em,
|
||||
private MonsterCategoryRepository $monsterCategoryRepository) {}
|
||||
|
||||
#[Route('', name: 'bo_monster_category_index', methods: ['GET'])]
|
||||
public function index(): Response {
|
||||
$monstersCategories = $this->monsterCategoryRepository->findBy(array(), array('name' => 'ASC'));
|
||||
|
||||
return $this->render('_dashboard/monster_category/index.html.twig', array(
|
||||
'monstersCategories' => $monstersCategories,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/new', name: 'bo_monster_category_new', methods: ['GET', 'POST'])]
|
||||
public function new(Request $request): RedirectResponse|Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
$monstersCategories = $this->monsterCategoryRepository->findBy(array(), array('name' => 'ASC'));
|
||||
|
||||
$monsterCategory = new MonsterCategory();
|
||||
$form = $this->monsterCategoryRepository->getForm('bo_monster_category_new', $monsterCategory);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted() && $form->isValid()) {
|
||||
$this->_em->persist($monsterCategory);
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->redirectToRoute('bo_monster_category_index', array(), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
|
||||
return $this->renderForm('_dashboard/monster_category/new.html.twig', array(
|
||||
'monstersCategories' => $monstersCategories,
|
||||
'monsterCategory' => $monsterCategory,
|
||||
'form' => $form,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/category-{id}', name: 'bo_monster_category_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, MonsterCategory $monsterCategory): RedirectResponse|Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
$monstersCategories = $this->monsterCategoryRepository->findBy(array(), array('name' => 'ASC'));
|
||||
|
||||
$form = $this->monsterCategoryRepository->getForm('bo_monster_category_edit', $monsterCategory);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted() && $form->isValid()) {
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->redirectToRoute('bo_monster_category_index', array(), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
|
||||
return $this->renderForm('_dashboard/monster_category/edit.html.twig', array(
|
||||
'monstersCategories' => $monstersCategories,
|
||||
'monsterCategory' => $monsterCategory,
|
||||
'form' => $form,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/delete-{id}', name: 'bo_monster_category_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, MonsterCategory $monsterCategory): RedirectResponse {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
if($this->isCsrfTokenValid('delete'.$monsterCategory->getId(), $request->request->get('_token'))) {
|
||||
$this->_em->remove($monsterCategory);
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
return $this->redirectToRoute('bo_monster_category_index', [], Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
}
|
||||
214
src/Controller/MonsterController.php
Normal file
214
src/Controller/MonsterController.php
Normal file
@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Monster;
|
||||
use App\Entity\MonsterCategory;
|
||||
use App\Repository\MonsterCategoryRepository;
|
||||
use App\Repository\MonsterRepository;
|
||||
use App\Service\FileManager;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route('/dashboard/monsters-categories/category-{monsterCategoryId}/monsters')]
|
||||
#[ParamConverter(data: 'monsterCategory', class: MonsterCategory::class, options: ['id' => 'monsterCategoryId'])]
|
||||
class MonsterController extends AbstractController {
|
||||
public function __construct(private EntityManagerInterface $_em,
|
||||
private FileManager $fileManager,
|
||||
private MonsterCategoryRepository $monsterCategoryRepository,
|
||||
private MonsterRepository $monsterRepository) {}
|
||||
|
||||
#[Route('', name: 'bo_monster_index', methods: ['GET'])]
|
||||
public function index(MonsterCategory $monsterCategory): Response {
|
||||
$monstersCategories = $this->monsterCategoryRepository->findBy(array(), array('name' => 'ASC'));
|
||||
$monsters = $this->monsterRepository->findBy(array('category' => $monsterCategory), array('name' => 'ASC'));
|
||||
|
||||
return $this->render('_dashboard/monster/index.html.twig', array(
|
||||
'monstersCategories' => $monstersCategories,
|
||||
'monsterCategory' => $monsterCategory,
|
||||
'monsters' => $monsters,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/new', name: 'bo_monster_new', methods: ['GET', 'POST'])]
|
||||
public function new(Request $request, MonsterCategory $monsterCategory): JsonResponse|Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_SENIOR');
|
||||
|
||||
if($request->isMethod('POST') && !$request->isXmlHttpRequest()) {
|
||||
throw new NotFoundHttpException("Page not found");
|
||||
}
|
||||
|
||||
$monstersCategories = $this->monsterCategoryRepository->findBy(array(), array('name' => 'ASC'));
|
||||
|
||||
$monster = new Monster();
|
||||
$monster->setCategory($monsterCategory);
|
||||
|
||||
$form = $this->monsterRepository->getForm('bo_monster_new', $monsterCategory, $monster);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted()) {
|
||||
if($form->isValid()) {
|
||||
if($monster->getIcon() instanceof UploadedFile) {
|
||||
$uploadedFile = $this->fileManager->uploadMonsterIcon($monster->getIcon());
|
||||
|
||||
if($uploadedFile['error']) {
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => $uploadedFile['message'],
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
$monster->setIcon($uploadedFile['filename']);
|
||||
}
|
||||
|
||||
$this->_em->persist($monster);
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'redirect',
|
||||
'params' => array(
|
||||
'url' => $this->generateUrl('bo_monster_index', array('monsterCategoryId' => $monsterCategory->getId())),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'Invalid form',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->renderForm('_dashboard/monster/new.html.twig', array(
|
||||
'monstersCategories' => $monstersCategories,
|
||||
'monsterCategory' => $monsterCategory,
|
||||
'monster' => $monster,
|
||||
'form' => $form,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/monster-{id}', name: 'bo_monster_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, MonsterCategory $monsterCategory, Monster $monster): JsonResponse|Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_SENIOR');
|
||||
|
||||
if($request->isMethod('POST') && !$request->isXmlHttpRequest()) {
|
||||
throw new NotFoundHttpException("Page not found");
|
||||
}
|
||||
|
||||
$monstersCategories = $this->monsterCategoryRepository->findBy(array(), array('name' => 'ASC'));
|
||||
|
||||
$icon = $monster->getIcon();
|
||||
|
||||
$form = $this->monsterRepository->getForm('bo_monster_edit', $monsterCategory, $monster);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted()) {
|
||||
if($form->isValid()) {
|
||||
if(!$form->get('removeFile')->getData()) {
|
||||
if($monster->getIcon() instanceof UploadedFile) {
|
||||
$uploadedFile = $this->fileManager->uploadMonsterIcon($monster->getIcon());
|
||||
|
||||
if($uploadedFile['error']) {
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => $uploadedFile['message'],
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
if($icon) {
|
||||
$this->fileManager->removeMonsterIcon($icon);
|
||||
}
|
||||
|
||||
$monster->setIcon($uploadedFile['filename']);
|
||||
} else {
|
||||
$monster->setIcon($icon);
|
||||
}
|
||||
} else {
|
||||
$this->fileManager->removeMonsterIcon($icon);
|
||||
|
||||
$monster->setIcon(null);
|
||||
}
|
||||
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'redirect',
|
||||
'params' => array(
|
||||
'url' => $this->generateUrl('bo_monster_index', array('monsterCategoryId' => $monsterCategory->getId())),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'Invalid form',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->renderForm('_dashboard/monster/edit.html.twig', array(
|
||||
'monstersCategories' => $monstersCategories,
|
||||
'monsterCategory' => $monsterCategory,
|
||||
'monster' => $monster,
|
||||
'form' => $form,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/delete-{id}', name: 'bo_monster_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, MonsterCategory $monsterCategory, Monster $monster): RedirectResponse {
|
||||
$this->denyAccessUnlessGranted('ROLE_SENIOR');
|
||||
|
||||
if($this->isCsrfTokenValid('delete'.$monster->getId(), $request->request->get('_token'))) {
|
||||
if($monster->getIcon()) {
|
||||
$this->fileManager->removeMonsterIcon($monster->getIcon());
|
||||
}
|
||||
|
||||
$this->_em->remove($monster);
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
return $this->redirectToRoute('bo_monster_index', array('monsterCategoryId' => $monsterCategory->getId()), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
}
|
||||
426
src/Controller/NodeController.php
Normal file
426
src/Controller/NodeController.php
Normal file
@ -0,0 +1,426 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Grid;
|
||||
use App\Entity\Node;
|
||||
use App\Entity\Worldmark;
|
||||
use App\Repository\NodeRepository;
|
||||
use App\Service\FileManager;
|
||||
use DateTime;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route('/dashboard/grid-{gridId}/worldmark-{worldmarkId}/nodes')]
|
||||
#[ParamConverter(data: 'grid', class: Grid::class, options: ['id' => 'gridId'])]
|
||||
#[ParamConverter(data: 'worldmark', class: Worldmark::class, options: ['id' => 'worldmarkId'])]
|
||||
class NodeController extends AbstractController {
|
||||
public function __construct(private EntityManagerInterface $_em,
|
||||
private FileManager $fileManager,
|
||||
private NodeRepository $nodeRepository) {}
|
||||
|
||||
#[Route('/new', name: 'bo_node_new', methods: ['POST'])]
|
||||
public function new(Request $request, Grid $grid, Worldmark $worldmark): JsonResponse {
|
||||
if($request->isXmlHttpRequest()) {
|
||||
if($this->isGranted('ROLE_CONTRIBUTOR')) {
|
||||
$node = new Node();
|
||||
$node->setGrid($grid)
|
||||
->setWorldmark($worldmark);
|
||||
|
||||
$form = $this->nodeRepository->getForm('bo_node_new', $grid, $worldmark, $node);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted()) {
|
||||
if($form->isValid()) {
|
||||
$errors = array();
|
||||
$uploadedFiles = array();
|
||||
$screenshotSetMethods = array('setScreenshotA', 'setScreenshotB', 'setScreenshotC', 'setScreenshotD', 'setScreenshotE');
|
||||
$screenshotGetMethods = array('getScreenshotA', 'getScreenshotB', 'getScreenshotC', 'getScreenshotD', 'getScreenshotE');
|
||||
|
||||
foreach($screenshotSetMethods as $key => $method) {
|
||||
if(is_callable(array($node, $method)) && is_callable(array($node, $screenshotGetMethods[$key]))) {
|
||||
$uploadedFiles[$method] = ($node->{$screenshotGetMethods[$key]}() instanceof UploadedFile)
|
||||
? $this->fileManager->uploadScreenshot($node->{$screenshotGetMethods[$key]}())
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($uploadedFiles as $method => $uploadedFile) {
|
||||
if($uploadedFile) {
|
||||
if($uploadedFile['error']) {
|
||||
$errors[] = $uploadedFile['message'];
|
||||
} elseif(is_callable(array($node, $method))) {
|
||||
$node->$method($uploadedFile['filename']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(count($errors)) {
|
||||
$messages = array();
|
||||
|
||||
foreach($screenshotGetMethods as $method) {
|
||||
if(is_callable(array($node, $method)) && is_string($node->$method())) {
|
||||
$this->fileManager->removeScreenshot($node->$method());
|
||||
}
|
||||
}
|
||||
|
||||
foreach($errors as $error) {
|
||||
$messages[] = array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => $error,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return $this->json(array('::function' => $messages));
|
||||
}
|
||||
|
||||
$this->_em->persist($node);
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name'=>'paq_event',
|
||||
'params' => array(
|
||||
'type' => 'trackEvent',
|
||||
'name' => "Contribution: Nodes",
|
||||
'value' => "Nodes created by {$this->getUser()->getUserIdentifier()}",
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'paq_event',
|
||||
'params' => array(
|
||||
'type' => 'trackEvent',
|
||||
'name' => "Contribution: {$node->getWorldmark()->getCategory()->getName()} nodes category",
|
||||
'value' => "Nodes created by {$this->getUser()->getUserIdentifier()}",
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'paq_event',
|
||||
'params' => array(
|
||||
'type' => 'trackEvent',
|
||||
'name' => "Contribution: {$node->getGrid()->getRegion()->getName()} nodes log",
|
||||
'value' => "[{$node->getModifiedAt()->format('Y-m-d H:i:s')}] Node {$node->getId()} was created by {$this->getUser()->getUserIdentifier()}",
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'node_validateForm',
|
||||
'params' => array(
|
||||
'gridId' => $grid->getId(),
|
||||
'htmlString' => $this->renderView('woldmap/_node.html.twig', array(
|
||||
'grid' => $grid,
|
||||
'worldmark' => $worldmark,
|
||||
'node' => $node,
|
||||
'directRender'=>true,
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'Invalid form',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'node_loadForm',
|
||||
'params' => array(
|
||||
'gridId' => $grid->getId(),
|
||||
'coordinate' => array('x' => '50', 'y' => '50'),
|
||||
'htmlString' => $this->renderView('_dashboard/node/_form.html.twig', array(
|
||||
'grid' => $grid,
|
||||
'worldmark' => $worldmark,
|
||||
'node' => $node,
|
||||
'form' => $form->createView(),
|
||||
)),
|
||||
'nodeId' => null,
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array('error' => 'Not found'), 404);
|
||||
}
|
||||
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
#[Route('/node-{id}', name: 'bo_node_edit', methods: ['POST'])]
|
||||
public function edit(Request $request, Grid $grid, Worldmark $worldmark, Node $node): JsonResponse {
|
||||
if($request->isXmlHttpRequest()) {
|
||||
if($this->isGranted('ROLE_CONTRIBUTOR')) {
|
||||
$screenshots = array(
|
||||
'ScreenshotA' => $node->getScreenshotA(),
|
||||
'ScreenshotB' => $node->getScreenshotB(),
|
||||
'ScreenshotC' => $node->getScreenshotC(),
|
||||
'ScreenshotD' => $node->getScreenshotD(),
|
||||
'ScreenshotE' => $node->getScreenshotE(),
|
||||
);
|
||||
|
||||
$form = $this->nodeRepository->getForm('bo_node_edit', $grid, $worldmark, $node);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted()) {
|
||||
if($form->isValid()) {
|
||||
$errors = array();
|
||||
$uploadedFiles = array();
|
||||
$screenshotSetMethods = array('setScreenshotA', 'setScreenshotB', 'setScreenshotC', 'setScreenshotD', 'setScreenshotE');
|
||||
$screenshotGetMethods = array('getScreenshotA', 'getScreenshotB', 'getScreenshotC', 'getScreenshotD', 'getScreenshotE');
|
||||
|
||||
foreach($screenshotSetMethods as $key => $method) {
|
||||
if(is_callable(array($node, $method)) && is_callable(array($node, $screenshotGetMethods[$key]))) {
|
||||
$uploadedFiles[$method] = ($node->{$screenshotGetMethods[$key]}() instanceof UploadedFile)
|
||||
? $this->fileManager->uploadScreenshot($node->{$screenshotGetMethods[$key]}())
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($uploadedFiles as $method => $uploadedFile) {
|
||||
if($uploadedFile) {
|
||||
if($uploadedFile['error']) {
|
||||
$errors[] = $uploadedFile['message'];
|
||||
} elseif(is_callable(array($node, $method))) {
|
||||
$node->$method($uploadedFile['filename']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(count($errors)) {
|
||||
$messages = array();
|
||||
|
||||
foreach($screenshotGetMethods as $method) {
|
||||
if(is_callable(array($node, $method)) && is_string($node->$method())) {
|
||||
$this->fileManager->removeScreenshot($node->$method());
|
||||
}
|
||||
}
|
||||
|
||||
foreach($errors as $error) {
|
||||
$messages[] = array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => $error,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return $this->json(array('::function' => $messages));
|
||||
}
|
||||
|
||||
foreach($screenshotGetMethods as $key => $method) {
|
||||
if(is_callable(array($node, $method))
|
||||
&& is_callable(array($node, $screenshotSetMethods[$key]))
|
||||
&& $node->$method() === null) {
|
||||
$node->{$screenshotSetMethods[$key]}($screenshots[substr($method, 3)]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->_em->persist($node);
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'paq_event',
|
||||
'params' => array(
|
||||
'type' => 'trackEvent',
|
||||
'name' => "Contribution: Nodes",
|
||||
'value' => "Nodes edited by {$this->getUser()->getUserIdentifier()}",
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name'=>'paq_event',
|
||||
'params' => array(
|
||||
'type' => 'trackEvent',
|
||||
'name' => "Contribution: {$node->getWorldmark()->getCategory()->getName()} nodes category",
|
||||
'value' => "Nodes edited by {$this->getUser()->getUserIdentifier()}",
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'paq_event',
|
||||
'params' => array(
|
||||
'type' => 'trackEvent',
|
||||
'name' => "Contribution: {$node->getGrid()->getRegion()->getName()} nodes log",
|
||||
'value' => "[{$node->getModifiedAt()->format('Y-m-d H:i:s')}] Node {$node->getId()} was edited by {$this->getUser()->getUserIdentifier()}",
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'node_validateForm',
|
||||
'params' => array(
|
||||
'gridId' => $grid->getId(),
|
||||
'htmlString' => $this->renderView('woldmap/_node.html.twig', array(
|
||||
'grid' => $grid,
|
||||
'worldmark' => $worldmark,
|
||||
'node' => $node,
|
||||
'directRender'=>true,
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'Invalid form',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'node_loadForm',
|
||||
'params' => array(
|
||||
'gridId' => $grid->getId(),
|
||||
'coordinate' => array('x' => '50', 'y' => '50'),
|
||||
'htmlString' => $this->renderView('_dashboard/node/_form.html.twig', array(
|
||||
'grid' => $grid,
|
||||
'worldmark' => $worldmark,
|
||||
'node' => $node,
|
||||
'form' => $form->createView(),
|
||||
)),
|
||||
'nodeId' => $node->getId(),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array('error' => 'Not found'), 404);
|
||||
}
|
||||
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
#[Route('/delete-{id}', name: 'bo_node_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, Grid $grid, Worldmark $worldmark, Node $node): JsonResponse {
|
||||
if($request->isXmlHttpRequest()) {
|
||||
if($this->isGranted('ROLE_CONTRIBUTOR')) {
|
||||
$form = $this->nodeRepository->getForm('bo_node_delete', $grid, $worldmark, $node);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted()) {
|
||||
if($form->isValid()) {
|
||||
$nodeId = $node->getId();
|
||||
|
||||
if($this->isGranted('ROLE_ADMIN')) {
|
||||
$screenshotGetMethods = array('getScreenshotA', 'getScreenshotB', 'getScreenshotC', 'getScreenshotD', 'getScreenshotE');
|
||||
|
||||
foreach($screenshotGetMethods as $method) {
|
||||
if(is_callable(array($node, $method)) && $node->$method() !== null) {
|
||||
$this->fileManager->removeScreenshot($node->$method());
|
||||
}
|
||||
}
|
||||
|
||||
$this->_em->remove($node);
|
||||
}
|
||||
|
||||
$this->_em->flush();
|
||||
|
||||
$deleteDate=new DateTime();
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name'=>'paq_event',
|
||||
'params' => array(
|
||||
'type' => 'trackEvent',
|
||||
'name' => "Contribution: Nodes",
|
||||
'value' => "Nodes deleted by {$this->getUser()->getUserIdentifier()}",
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'paq_event',
|
||||
'params' => array(
|
||||
'type' => 'trackEvent',
|
||||
'name' => "Contribution: {$node->getWorldmark()->getCategory()->getName()} nodes category",
|
||||
'value' => "Nodes deleted by {$this->getUser()->getUserIdentifier()}",
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'paq_event',
|
||||
'params' => array(
|
||||
'type' => 'trackEvent',
|
||||
'name' => "Contribution: {$node->getGrid()->getRegion()->getName()} nodes log",
|
||||
'value' => "[{$deleteDate->format('Y-m-d H:i:s')}] Node {$node->getId()} was deleted by {$this->getUser()->getUserIdentifier()}",
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'node_removeElement',
|
||||
'params' => array(
|
||||
'gridId' => $grid->getId(),
|
||||
'nodeId' => $nodeId,
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'modal_unload',
|
||||
'params' => null,
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'Invalid form',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'modal_load',
|
||||
'params' => array(
|
||||
'htmlString' => $this->renderView('_dashboard/node/_delete_form.html.twig', array(
|
||||
'grid' => $grid,
|
||||
'worldmark' => $worldmark,
|
||||
'node' => $node,
|
||||
'form' => $form->createView(),
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array('error' => 'Not found'), 404);
|
||||
}
|
||||
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
}
|
||||
179
src/Controller/RegionController.php
Normal file
179
src/Controller/RegionController.php
Normal file
@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Grid;
|
||||
use App\Entity\Region;
|
||||
use App\Kernel;
|
||||
use App\Repository\GridRepository;
|
||||
use App\Repository\MapRepository;
|
||||
use App\Repository\NodeRepository;
|
||||
use App\Repository\RegionRepository;
|
||||
use App\Repository\WorldmarkCategoryRepository;
|
||||
use App\Repository\WorldmarkRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class RegionController extends AbstractController {
|
||||
public function __construct(private EntityManagerInterface $_em,
|
||||
private RegionRepository $regionRepository,
|
||||
private GridRepository $gridRepository,
|
||||
private MapRepository $mapRepository,
|
||||
private WorldmarkCategoryRepository $worldmarkCategoryRepository,
|
||||
private WorldmarkRepository $worldmarkRepository,
|
||||
private NodeRepository $nodeRepository) {}
|
||||
|
||||
#[Route('/worldmap', name: 'fo_worldmap_redirect_a', methods: ['GET'])]
|
||||
public function redirectA(): RedirectResponse {
|
||||
return $this->redirectToRoute('fo_region_show', array('slug'=>'mondstadt'), Response::HTTP_MOVED_PERMANENTLY);
|
||||
}
|
||||
|
||||
#[Route('/worldmap/{slug}', name: 'fo_worldmap_redirect_b', methods: ['GET'])]
|
||||
public function redirectB(Region $region): RedirectResponse {
|
||||
return $this->redirectToRoute('fo_region_show', array('slug'=>$region->getSlug()), Response::HTTP_MOVED_PERMANENTLY);
|
||||
}
|
||||
|
||||
#[Route('/{slug}', name: 'fo_region_show', methods: ['GET'])]
|
||||
public function show(Request $request, ?Region $region): Response {
|
||||
$version = $request->query->get('v');
|
||||
|
||||
if(!$version
|
||||
|| !in_array(floatval($version), Kernel::SUPPORTED_GAME_VERSION)
|
||||
|| (floatval($version) < Kernel::GAME_VERSION && !$this->isGranted('ROLE_ADMIN'))
|
||||
|| (floatval($version) > Kernel::GAME_VERSION && !$this->isGranted('ROLE_CONTRIBUTOR'))) {
|
||||
$version = Kernel::GAME_VERSION;
|
||||
} else {
|
||||
$version = floatval($version);
|
||||
}
|
||||
|
||||
if(!$region
|
||||
|| $region->getVersion() > $version
|
||||
|| !$region->getIsActive() && !$this->isGranted('ROLE_CONTRIBUTOR')) {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$_region = $region->getIsAlias() ? $region->getParentRegion() : $region;
|
||||
|
||||
$cells = $this->gridRepository->getGridCells($_region);
|
||||
$maps = $this->mapRepository->getCellsMap($cells, $version);
|
||||
$grid = $this->gridRepository->buildWorldmap($version, $cells, $maps, true);
|
||||
|
||||
$worldmarks = $this->worldmarkRepository->getRegionWorldmarks($_region, $version);
|
||||
$nodes = $this->nodeRepository->getGridNodes($cells, $worldmarks, $version, $this->isGranted('ROLE_ADMIN'));
|
||||
|
||||
$worldmarksData = array();
|
||||
foreach($worldmarks as $worldmark) {
|
||||
if(!array_key_exists($worldmark->getCategory()->getSlug(), $worldmarksData)) {
|
||||
$worldmarksData[$worldmark->getCategory()->getSlug()]['_data'] = $worldmark->getCategory();
|
||||
$worldmarksData[$worldmark->getCategory()->getSlug()]['_worldmarks'] = array();
|
||||
}
|
||||
|
||||
$worldmarksData[$worldmark->getCategory()->getSlug()]['_worldmarks'][] = $worldmark;
|
||||
}
|
||||
|
||||
$nodesData = array();
|
||||
foreach($nodes as $node) {
|
||||
$nodesData["grid_{$node->getGrid()->getId()}"][] = $node;
|
||||
}
|
||||
|
||||
return $this->render('woldmap/show.html.twig', array(
|
||||
// 'title' => "Genshin Impact interactive map of {$_region->getName()}",
|
||||
'title' => "{$_region->getName()} interactive map - Genshin Impact - Genshin World",
|
||||
'region' => $_region,
|
||||
'regionSlug' => $region->getSlug(),
|
||||
'version' => $version,
|
||||
'grid' => $grid,
|
||||
'worldmarksData' => $worldmarksData,
|
||||
'nodes' => $nodesData,
|
||||
'anchor' => $region->getIsAlias() ? $region->getAnchor() : null,
|
||||
'filter'=>$request->get('filter'),
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/dashboard/regions', name: 'bo_region_index', methods: ['GET'])]
|
||||
public function index(): Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
return $this->render('_dashboard/region/index.html.twig', array(
|
||||
'title' => "Dashboard: Regions index",
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/dashboard/regions/new', name: 'bo_region_new', methods: ['GET', 'POST'])]
|
||||
public function new(Request $request): Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
$region = new Region();
|
||||
$form = $this->regionRepository->getForm('bo_region_new', $region);
|
||||
|
||||
$form->handleRequest($request);
|
||||
if($form->isSubmitted() && $form->isValid()) {
|
||||
$this->_em->persist($region);
|
||||
|
||||
if($region->getIsAlias()) {
|
||||
$region->setGridHeight(0);
|
||||
$region->setGridWidth(0);
|
||||
}
|
||||
|
||||
if($region->getGridHeight() > 0 && $region->getGridWidth() > 0) {
|
||||
for($row = 1; $row <= $region->getGridHeight(); $row++) {
|
||||
for($col = 1; $col <= $region->getGridWidth(); $col++) {
|
||||
$grid = new Grid();
|
||||
|
||||
$grid->setRegion($region)
|
||||
->setRow($row)
|
||||
->setCol($col);
|
||||
|
||||
$this->_em->persist($grid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->redirectToRoute('bo_region_index', array(), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
|
||||
return $this->renderForm('_dashboard/region/new.html.twig', array(
|
||||
'title' => "Dashboard: Create region",
|
||||
'region' => $region,
|
||||
'form' => $form,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/dashboard/regions/region-{id}', name: 'bo_region_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, Region $region): Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
$form = $this->regionRepository->getForm('bo_region_edit', $region);
|
||||
|
||||
$form->handleRequest($request);
|
||||
if($form->isSubmitted() && $form->isValid()) {
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->redirectToRoute('bo_region_index', array(), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
|
||||
return $this->renderForm('_dashboard/region/edit.html.twig', array(
|
||||
'title' => "Dashboard: Edit region",
|
||||
'region' => $region,
|
||||
'form' => $form,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/dashboard/regions/delete-{id}', name: 'bo_region_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, Region $region): RedirectResponse {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
if($this->isCsrfTokenValid('delete'.$region->getId(), $request->request->get('_token'))) {
|
||||
$this->_em->remove($region);
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
return $this->redirectToRoute('bo_region_index', array(), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
}
|
||||
71
src/Controller/SecurityController.php
Normal file
71
src/Controller/SecurityController.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Repository\UserRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
|
||||
|
||||
class SecurityController extends AbstractController {
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $_em,
|
||||
private readonly UserRepository $userRepository,
|
||||
private readonly UserPasswordHasherInterface $userPasswordHasher) {
|
||||
}
|
||||
|
||||
// #[Route('/035c7785-2c2f-11ec-aaf0-ac1f6b44f230/register', name: 'security_register')]
|
||||
public function register(Request $request): Response {
|
||||
$user = new User();
|
||||
$form = $this->userRepository->getForm('security_register', $user);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted() && $form->isValid()) {
|
||||
// encode the plain password
|
||||
$user->setPassword(
|
||||
$this->userPasswordHasher->hashPassword(
|
||||
$user,
|
||||
$form->get('plainPassword')->getData()
|
||||
)
|
||||
);
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
|
||||
// do anything else you need here, like send an email
|
||||
|
||||
return $this->redirectToRoute('security_login', array(), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
|
||||
return $this->renderForm('security/register.html.twig', array(
|
||||
'form' => $form,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route(path: '/035c7785-2c2f-11ec-aaf0-ac1f6b44f230/login', name: 'security_login')]
|
||||
public function login(AuthenticationUtils $authenticationUtils): Response {
|
||||
// if ($this->getUser()) {
|
||||
// return $this->redirectToRoute('target_path');
|
||||
// }
|
||||
|
||||
// get the login error if there is one
|
||||
$error = $authenticationUtils->getLastAuthenticationError();
|
||||
// last username entered by the user
|
||||
$lastUsername = $authenticationUtils->getLastUsername();
|
||||
|
||||
return $this->render('security/login.html.twig', array(
|
||||
'last_username' => $lastUsername,
|
||||
'error' => $error,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route(path: '/035c7785-2c2f-11ec-aaf0-ac1f6b44f230/logout', name: 'security_logout')]
|
||||
public function logout(): void {
|
||||
// throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
|
||||
}
|
||||
}
|
||||
81
src/Controller/WorldmarkCategoryController.php
Normal file
81
src/Controller/WorldmarkCategoryController.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\WorldmarkCategory;
|
||||
use App\Repository\WorldmarkCategoryRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route('/dashboard/worldmarks-categories')]
|
||||
class WorldmarkCategoryController extends AbstractController {
|
||||
public function __construct(private EntityManagerInterface $_em,
|
||||
private WorldmarkCategoryRepository $worldmarkCategoryRepository) {}
|
||||
|
||||
#[Route('', name: 'bo_worldmark_category_index', methods: ['GET'])]
|
||||
public function index(): Response {
|
||||
return $this->render('_dashboard/worldmark_category/index.html.twig', array(
|
||||
'worldmarksCategories' => $this->worldmarkCategoryRepository->findBy(array(), array('sortOrder' => 'ASC'))
|
||||
));
|
||||
}
|
||||
|
||||
//ToDo set foirm to XHR for errors
|
||||
#[Route('/new', name: 'bo_worldmark_category_new', methods: ['GET', 'POST'])]
|
||||
public function new(Request $request): Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
$category=new WorldmarkCategory();
|
||||
$form=$this->worldmarkCategoryRepository->getForm('bo_worldmark_category_new', $category);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted() && $form->isValid()) {
|
||||
$this->_em->persist($category);
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->redirectToRoute('bo_worldmark_category_index', array(), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
|
||||
return $this->renderForm('_dashboard/worldmark_category/new.html.twig', array(
|
||||
'worldmarksCategories' => $this->worldmarkCategoryRepository->findBy(array(), array('sortOrder' => 'ASC')),
|
||||
'worldmarkCategory'=>$category,
|
||||
'form'=>$form,
|
||||
));
|
||||
}
|
||||
|
||||
//ToDo set foirm to XHR for errors
|
||||
#[Route('/category-{id}', name: 'bo_worldmark_category_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, WorldmarkCategory $worldmarkCategory): Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
$form=$this->worldmarkCategoryRepository->getForm('bo_worldmark_category_edit', $worldmarkCategory);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted() && $form->isValid()) {
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->redirectToRoute('bo_worldmark_category_index', array(), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
|
||||
return $this->renderForm('_dashboard/worldmark_category/edit.html.twig', array(
|
||||
'worldmarksCategories' => $this->worldmarkCategoryRepository->findBy(array(), array('sortOrder' => 'ASC')),
|
||||
'worldmarkCategory'=>$worldmarkCategory,
|
||||
'form'=>$form,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/delete-{id}', name: 'bo_worldmark_category_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, WorldmarkCategory $worldmarkCategory): RedirectResponse {
|
||||
$this->denyAccessUnlessGranted('ROLE_ADMIN');
|
||||
|
||||
if($this->isCsrfTokenValid('delete'.$worldmarkCategory->getId(), $request->request->get('_token'))) {
|
||||
$this->_em->remove($worldmarkCategory);
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
return $this->redirectToRoute('bo_worldmark_category_index', array(), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
}
|
||||
240
src/Controller/WorldmarkController.php
Normal file
240
src/Controller/WorldmarkController.php
Normal file
@ -0,0 +1,240 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Worldmark;
|
||||
use App\Entity\WorldmarkCategory;
|
||||
use App\Repository\ItemCategoryRepository;
|
||||
use App\Repository\MonsterCategoryRepository;
|
||||
use App\Repository\WorldmarkCategoryRepository;
|
||||
use App\Repository\WorldmarkRepository;
|
||||
use App\Service\FileManager;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route('/dashboard/worldmarks-categories/category-{worldmarkCategoryId}/worldmarks')]
|
||||
#[ParamConverter(data: 'worldmarkCategory', class: WorldmarkCategory::class, options: ['id' => 'worldmarkCategoryId'])]
|
||||
class WorldmarkController extends AbstractController {
|
||||
public function __construct(private EntityManagerInterface $_em,
|
||||
private FileManager $fileManager,
|
||||
private WorldmarkCategoryRepository $worldmarkCategoryRepository,
|
||||
private ItemCategoryRepository $itemCategoryRepository,
|
||||
private MonsterCategoryRepository $monsterCategoryRepository,
|
||||
private WorldmarkRepository $worldmarkRepository) {}
|
||||
|
||||
#[Route('', name: 'bo_worldmark_index', methods: ['GET'])]
|
||||
public function index(WorldmarkCategory $worldmarkCategory): Response {
|
||||
$worldmarksCategories = $this->worldmarkCategoryRepository->findBy(array(), array('sortOrder' => 'ASC'));
|
||||
$worldmarks = $this->worldmarkRepository->findBy(array('category' => $worldmarkCategory), array('sortOrder' => 'ASC'));
|
||||
|
||||
return $this->render('_dashboard/worldmark/index.html.twig', array(
|
||||
'worldmarksCategories' => $worldmarksCategories,
|
||||
'worldmarkCategory' => $worldmarkCategory,
|
||||
'worldmarks' => $worldmarks,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/new', name: 'bo_worldmark_new', methods: ['GET', 'POST'])]
|
||||
public function new(Request $request, WorldmarkCategory $worldmarkCategory): JsonResponse|Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_SENIOR');
|
||||
|
||||
if($request->isMethod('POST') && !$request->isXmlHttpRequest()) {
|
||||
throw new NotFoundHttpException("Page not found");
|
||||
}
|
||||
|
||||
$worldmark = new Worldmark();
|
||||
$worldmark->setCategory($worldmarkCategory);
|
||||
|
||||
$form = $this->worldmarkRepository->getForm('bo_worldmark_new', $worldmarkCategory, $worldmark);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted()) {
|
||||
if($form->isValid()) {
|
||||
if($worldmark->getItem() || $worldmark->getMonster() || $worldmark->getIcon() instanceof UploadedFile) {
|
||||
if($worldmark->getItem()) {
|
||||
$uploadedFile = $this->fileManager->getWorldmarkIconFromEntity($worldmark->getItem());
|
||||
} elseif($worldmark->getMonster()) {
|
||||
$uploadedFile = $this->fileManager->getWorldmarkIconFromEntity($worldmark->getMonster());
|
||||
} elseif($worldmark->getIcon() instanceof UploadedFile) {
|
||||
$uploadedFile = $this->fileManager->uploadWorldmarkIcon($worldmark->getIcon());
|
||||
} else {
|
||||
$uploadedFile = array(
|
||||
'error' => true,
|
||||
'filename' => null,
|
||||
'message' => 'An internal error occurred',
|
||||
);
|
||||
}
|
||||
|
||||
if($uploadedFile['error']) {
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => $uploadedFile['message'],
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
$worldmark->setIcon($uploadedFile['filename']);
|
||||
}
|
||||
|
||||
$this->_em->persist($worldmark);
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'redirect',
|
||||
'params' => array(
|
||||
'url' => $this->generateUrl('bo_worldmark_index', array('worldmarkCategoryId' => $worldmarkCategory->getId())),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'Invalid form',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
$worldmarksCategories = $this->worldmarkCategoryRepository->findBy(array(), array('sortOrder' => 'ASC'));
|
||||
|
||||
return $this->renderForm('_dashboard/worldmark/new.html.twig', array(
|
||||
'worldmarksCategories' => $worldmarksCategories,
|
||||
'worldmarkCategory' => $worldmarkCategory,
|
||||
'worldmark' => $worldmark,
|
||||
'form' => $form,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/worldmark-{id}', name: 'bo_worldmark_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, WorldmarkCategory $worldmarkCategory, Worldmark $worldmark): JsonResponse|Response {
|
||||
$this->denyAccessUnlessGranted('ROLE_SENIOR');
|
||||
|
||||
if($request->isMethod('POST') && !$request->isXmlHttpRequest()) {
|
||||
throw new NotFoundHttpException("Page not found");
|
||||
}
|
||||
|
||||
$icon = $worldmark->getIcon();
|
||||
$item = $worldmark->getItem();
|
||||
$monster = $worldmark->getMonster();
|
||||
|
||||
$form = $this->worldmarkRepository->getForm('bo_worldmark_edit', $worldmarkCategory, $worldmark);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if($form->isSubmitted()) {
|
||||
if($form->isValid()) {
|
||||
if(($worldmark->getItem() && $worldmark->getItem()->getId() !== $item->getId())
|
||||
|| ($worldmark->getMonster() && $worldmark->getMonster()->getId() !== $monster->getId())
|
||||
|| $worldmark->getIcon() instanceof UploadedFile) {
|
||||
if($worldmark->getItem()) {
|
||||
$uploadedFile = $this->fileManager->getWorldmarkIconFromEntity($worldmark->getItem());
|
||||
} elseif($worldmark->getMonster()) {
|
||||
$uploadedFile = $this->fileManager->getWorldmarkIconFromEntity($worldmark->getMonster());
|
||||
} elseif($worldmark->getIcon() instanceof UploadedFile) {
|
||||
$uploadedFile = $this->fileManager->uploadWorldmarkIcon($worldmark->getIcon());
|
||||
} else {
|
||||
$uploadedFile = array(
|
||||
'error' => true,
|
||||
'filename' => null,
|
||||
'message' => 'An internal error occurred',
|
||||
);
|
||||
}
|
||||
|
||||
if($uploadedFile['error']) {
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => $uploadedFile['message'],
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
if($icon) {
|
||||
$this->fileManager->removeWorldmarkIcon($icon);
|
||||
}
|
||||
|
||||
$worldmark->setIcon($uploadedFile['filename']);
|
||||
} else {
|
||||
$worldmark->setIcon($icon);
|
||||
}
|
||||
|
||||
$this->_em->flush();
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'redirect',
|
||||
'params' => array(
|
||||
'url' => $this->generateUrl('bo_worldmark_index', array('worldmarkCategoryId' => $worldmarkCategory->getId())),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return $this->json(array(
|
||||
'::function' => array(
|
||||
array(
|
||||
'name' => 'messageInfo',
|
||||
'params' => array(
|
||||
'type' => 'error',
|
||||
'message' => 'Invalid form',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
$worldmarksCategories = $this->worldmarkCategoryRepository->findBy(array(), array('sortOrder' => 'ASC'));
|
||||
|
||||
return $this->renderForm('_dashboard/worldmark/edit.html.twig', array(
|
||||
'worldmarksCategories' => $worldmarksCategories,
|
||||
'worldmarkCategory' => $worldmarkCategory,
|
||||
'worldmark' => $worldmark,
|
||||
'form' => $form,
|
||||
));
|
||||
}
|
||||
|
||||
#[Route('/delete-{id}', name: 'bo_worldmark_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, WorldmarkCategory $worldmarkCategory, Worldmark $worldmark): RedirectResponse {
|
||||
$this->denyAccessUnlessGranted('ROLE_SENIOR');
|
||||
|
||||
if($this->isCsrfTokenValid('delete'.$worldmark->getId(), $request->request->get('_token'))) {
|
||||
if($worldmark->getIcon()) {
|
||||
$this->fileManager->removeWorldmarkIcon($worldmark->getIcon());
|
||||
}
|
||||
|
||||
$this->_em->remove($worldmark);
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
return $this->redirectToRoute('bo_worldmark_index', array('worldmarkCategoryId' => $worldmarkCategory->getId()), Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
}
|
||||
67
src/Doctrine/DBAL/Types/TinyintType.php
Normal file
67
src/Doctrine/DBAL/Types/TinyintType.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Doctrine\DBAL\Types;
|
||||
|
||||
use Doctrine\DBAL\ParameterType;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
|
||||
class TinyintType extends Type {
|
||||
private const TINYINT='tinyint';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string {
|
||||
return self::TINYINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $column
|
||||
* @param AbstractPlatform $platform
|
||||
* @return string
|
||||
*/
|
||||
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string {
|
||||
$declaration="TINYINT(1)";
|
||||
|
||||
if(array_key_exists('unsigned', $column) && $column['unsigned'] === true) {
|
||||
$declaration.=" UNSIGNED";
|
||||
}
|
||||
|
||||
$declaration.=" COMMENT '(DC2Type:tinyint)'";
|
||||
|
||||
return $declaration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function canRequireSQLConversion(): bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @param AbstractPlatform $platform
|
||||
* @return int|null
|
||||
*/
|
||||
public function convertToPHPValue($value, AbstractPlatform $platform): ?int {
|
||||
return $value === null ? null : (int)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @param AbstractPlatform $platform
|
||||
* @return int|null
|
||||
*/
|
||||
public function convertToDatabaseValue($value, AbstractPlatform $platform): ?int {
|
||||
return $value === null ? null : (int)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getBindingType(): int {
|
||||
return ParameterType::INTEGER;
|
||||
}
|
||||
}
|
||||
0
src/Entity/.gitignore
vendored
Normal file
0
src/Entity/.gitignore
vendored
Normal file
58
src/Entity/Grid.php
Normal file
58
src/Entity/Grid.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\GridRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: GridRepository::class)]
|
||||
class Grid {
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
|
||||
private $id;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Region::class)]
|
||||
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
|
||||
private $region;
|
||||
|
||||
#[ORM\Column(name: '`row`', type: 'tinyint')]
|
||||
private $row;
|
||||
|
||||
#[ORM\Column(type: 'tinyint')]
|
||||
private $col;
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getRegion(): ?Region {
|
||||
return $this->region;
|
||||
}
|
||||
|
||||
public function setRegion(?Region $region): self {
|
||||
$this->region=$region;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRow() {
|
||||
return $this->row;
|
||||
}
|
||||
|
||||
public function setRow($row): self {
|
||||
$this->row=$row;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCol() {
|
||||
return $this->col;
|
||||
}
|
||||
|
||||
public function setCol($col): self {
|
||||
$this->col=$col;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
106
src/Entity/Item.php
Normal file
106
src/Entity/Item.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\ItemRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
#[ORM\Entity(repositoryClass: ItemRepository::class)]
|
||||
#[ORM\Index(columns: ['slug'])]
|
||||
#[UniqueEntity(fields: ['slug'], message: 'There is already an item with this slug')]
|
||||
class Item {
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
|
||||
private $id;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: ItemCategory::class)]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
private $category;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 60)]
|
||||
private $name;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 60, unique: true)]
|
||||
private $slug;
|
||||
|
||||
#[ORM\Column(type: 'text', nullable: true)]
|
||||
private $description;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, nullable: true)]
|
||||
private $icon;
|
||||
|
||||
#[ORM\Column(type: 'float')]
|
||||
private $version;
|
||||
|
||||
public function __toString(): string {
|
||||
return $this->getName();
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getCategory(): ItemCategory {
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
public function setCategory(ItemCategory $category): self {
|
||||
$this->category = $category;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): ?string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): self {
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSlug(): ?string {
|
||||
return $this->slug;
|
||||
}
|
||||
|
||||
public function setSlug(string $slug): self {
|
||||
$this->slug = $slug;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(?string $description): self {
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getIcon(): string|UploadedFile|null {
|
||||
return $this->icon;
|
||||
}
|
||||
|
||||
public function setIcon(string|UploadedFile|null $icon): self {
|
||||
$this->icon = $icon;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVersion(): ?float {
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
public function setVersion(float $version): self {
|
||||
$this->version = $version;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
65
src/Entity/ItemCategory.php
Normal file
65
src/Entity/ItemCategory.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\ItemCategoryRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
#[ORM\Entity(repositoryClass: ItemCategoryRepository::class)]
|
||||
#[ORM\Index(columns: ['slug'])]
|
||||
#[UniqueEntity(fields: ['name'], message: 'There is already an item category with this name')]
|
||||
#[UniqueEntity(fields: ['slug'], message: 'There is already an item category with this slug')]
|
||||
class ItemCategory {
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
|
||||
private $id;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, unique: true)]
|
||||
private $name;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, unique: true)]
|
||||
private $slug;
|
||||
|
||||
#[ORM\Column(type: 'smallint', options: ['default' => 65535, 'unsigned' => true])]
|
||||
private $sortOrder;
|
||||
|
||||
public function __toString(): string {
|
||||
return $this->getName();
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getName(): ?string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): self {
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSlug(): ?string {
|
||||
return $this->slug;
|
||||
}
|
||||
|
||||
public function setSlug(string $slug): self {
|
||||
$this->slug = $slug;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSortOrder(): ?int {
|
||||
return $this->sortOrder;
|
||||
}
|
||||
|
||||
public function setSortOrder(int $sortOrder): self {
|
||||
$this->sortOrder = $sortOrder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
89
src/Entity/Map.php
Normal file
89
src/Entity/Map.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\MapRepository;
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
#[ORM\Entity(repositoryClass: MapRepository::class)]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[UniqueEntity(fields: ['file'], message: 'There is already a file with this name')]
|
||||
class Map {
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
|
||||
private $id;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Grid::class)]
|
||||
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
|
||||
private $grid;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, unique: true)]
|
||||
private $file;
|
||||
|
||||
#[ORM\Column(type: 'datetime')]
|
||||
private $modifiedAt;
|
||||
|
||||
#[ORM\Column(type: 'float')]
|
||||
private $version;
|
||||
|
||||
public function __toString(): string {
|
||||
return $this->getFile();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
#[ORM\PreUpdate]
|
||||
public function updateLifecycle() {
|
||||
$this->setModifiedAt(new DateTime());
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getGrid(): ?Grid
|
||||
{
|
||||
return $this->grid;
|
||||
}
|
||||
|
||||
public function setGrid(?Grid $grid): self
|
||||
{
|
||||
$this->grid = $grid;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFile(): string|UploadedFile|null {
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
public function setFile(string|UploadedFile|null $file): self {
|
||||
$this->file=$file;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getModifiedAt(): ?DateTimeInterface {
|
||||
return $this->modifiedAt;
|
||||
}
|
||||
|
||||
public function setModifiedAt(DateTimeInterface $modifiedAt): self {
|
||||
$this->modifiedAt=$modifiedAt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVersion(): ?float {
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
public function setVersion(float $version): self {
|
||||
$this->version=$version;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
105
src/Entity/Monster.php
Normal file
105
src/Entity/Monster.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\MonsterRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
#[ORM\Entity(repositoryClass: MonsterRepository::class)]
|
||||
#[ORM\Index(columns: ['slug'])]
|
||||
#[UniqueEntity(fields: ['slug'], message: 'There is already a monster with this slug')]
|
||||
class Monster {
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
|
||||
private $id;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: MonsterCategory::class)]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
private $category;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 60)]
|
||||
private $name;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 60, unique: true)]
|
||||
private $slug;
|
||||
|
||||
#[ORM\Column(type: 'text', nullable: true)]
|
||||
private $description;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, nullable: true)]
|
||||
private $icon;
|
||||
|
||||
#[ORM\Column(type: 'float')]
|
||||
private $version;
|
||||
|
||||
public function __toString(): string {
|
||||
return $this->getName();
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getCategory(): MonsterCategory {
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
public function setCategory(MonsterCategory $category): self {
|
||||
$this->category=$category;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): ?string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): self {
|
||||
$this->name=$name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSlug(): ?string {
|
||||
return $this->slug;
|
||||
}
|
||||
|
||||
public function setSlug(string $slug): self {
|
||||
$this->slug=$slug;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(?string $description): self {
|
||||
$this->description=$description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIcon(): string|UploadedFile|null {
|
||||
return $this->icon;
|
||||
}
|
||||
|
||||
public function setIcon(string|UploadedFile|null $icon): self {
|
||||
$this->icon=$icon;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVersion(): ?float {
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
public function setVersion(float $version): self {
|
||||
$this->version=$version;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
52
src/Entity/MonsterCategory.php
Normal file
52
src/Entity/MonsterCategory.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\MonsterCategoryRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
#[ORM\Entity(repositoryClass: MonsterCategoryRepository::class)]
|
||||
#[ORM\Index(columns: ['slug'])]
|
||||
#[UniqueEntity(fields: ['name'], message: 'There is already a monster category with this name')]
|
||||
#[UniqueEntity(fields: ['slug'], message: 'There is already a monster category with this slug')]
|
||||
class MonsterCategory {
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
|
||||
private $id;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, unique: true)]
|
||||
private $name;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, unique: true)]
|
||||
private $slug;
|
||||
|
||||
public function __toString(): string {
|
||||
return $this->getName();
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getName(): ?string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): self {
|
||||
$this->name=$name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSlug(): ?string {
|
||||
return $this->slug;
|
||||
}
|
||||
|
||||
public function setSlug(string $slug): self {
|
||||
$this->slug=$slug;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
230
src/Entity/Node.php
Normal file
230
src/Entity/Node.php
Normal file
@ -0,0 +1,230 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\NodeRepository;
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
#[ORM\Entity(repositoryClass: NodeRepository::class)]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
class Node {
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
|
||||
private ?int $id;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Grid::class)]
|
||||
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
|
||||
private ?Grid $grid;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Worldmark::class)]
|
||||
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
|
||||
private ?Worldmark $worldmark;
|
||||
|
||||
#[ORM\Column(type: 'text', nullable: true)]
|
||||
private ?string $description;
|
||||
|
||||
#[ORM\Column(type: 'tinyint', options: ['default' => 1])]
|
||||
private int $quantity;
|
||||
|
||||
#[ORM\Column(type: 'smallint', options: ['default' => 0, 'unsigned' => true])]
|
||||
private ?int $primogem;
|
||||
|
||||
#[ORM\Column(type: 'json')]
|
||||
private array $coordinate;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, nullable: true)]
|
||||
private string|UploadedFile|null $screenshotA;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, nullable: true)]
|
||||
private string|UploadedFile|null $screenshotB;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, nullable: true)]
|
||||
private string|UploadedFile|null $screenshotC;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, nullable: true)]
|
||||
private string|UploadedFile|null $screenshotD;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, nullable: true)]
|
||||
private string|UploadedFile|null $screenshotE;
|
||||
|
||||
#[ORM\Column(type: 'datetime')]
|
||||
private ?DateTimeInterface $modifiedAt;
|
||||
|
||||
#[ORM\Column(type: 'float')]
|
||||
private ?float $version;
|
||||
|
||||
#[ORM\Column(type: 'boolean')]
|
||||
private bool $isDeleted;
|
||||
|
||||
public function __construct() {
|
||||
$this->id = null;
|
||||
$this->description = null;
|
||||
$this->quantity = 1;
|
||||
$this->primogem = 0;
|
||||
$this->coordinate = array(
|
||||
'x' => 50,
|
||||
'y' => 50,
|
||||
);
|
||||
$this->screenshotA = null;
|
||||
$this->screenshotB = null;
|
||||
$this->screenshotC = null;
|
||||
$this->screenshotD = null;
|
||||
$this->screenshotE = null;
|
||||
$this->version = null;
|
||||
$this->isDeleted = false;
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
#[ORM\PreUpdate]
|
||||
public function updateLifecycle() {
|
||||
$this->setModifiedAt(new DateTime());
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getGrid(): ?Grid {
|
||||
return $this->grid;
|
||||
}
|
||||
|
||||
public function setGrid(?Grid $grid): self {
|
||||
$this->grid = $grid;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getWorldmark(): ?Worldmark {
|
||||
return $this->worldmark;
|
||||
}
|
||||
|
||||
public function setWorldmark(?Worldmark $worldmark): self {
|
||||
$this->worldmark = $worldmark;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(?string $description): self {
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getQuantity(): int {
|
||||
return $this->quantity;
|
||||
}
|
||||
|
||||
public function setQuantity($quantity): self {
|
||||
$this->quantity = $quantity;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPrimogem(): int {
|
||||
return $this->primogem;
|
||||
}
|
||||
|
||||
public function setPrimogem($primogem): self {
|
||||
$this->primogem = $primogem;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCoordinate(): array {
|
||||
return $this->coordinate;
|
||||
}
|
||||
|
||||
public function setCoordinate(array $coordinate): self {
|
||||
$this->coordinate = $coordinate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getScreenshotA(): string|UploadedFile|null {
|
||||
return $this->screenshotA;
|
||||
}
|
||||
|
||||
public function setScreenshotA(string|UploadedFile|null $screenshotA): self {
|
||||
$this->screenshotA = $screenshotA;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getScreenshotB(): string|UploadedFile|null {
|
||||
return $this->screenshotB;
|
||||
}
|
||||
|
||||
public function setScreenshotB(string|UploadedFile|null $screenshotB): self {
|
||||
$this->screenshotB = $screenshotB;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getScreenshotC(): string|UploadedFile|null {
|
||||
return $this->screenshotC;
|
||||
}
|
||||
|
||||
public function setScreenshotC(string|UploadedFile|null $screenshotC): self {
|
||||
$this->screenshotC = $screenshotC;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getScreenshotD(): string|UploadedFile|null {
|
||||
return $this->screenshotD;
|
||||
}
|
||||
|
||||
public function setScreenshotD(string|UploadedFile|null $screenshotD): self {
|
||||
$this->screenshotD = $screenshotD;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getScreenshotE(): string|UploadedFile|null {
|
||||
return $this->screenshotE;
|
||||
}
|
||||
|
||||
public function setScreenshotE(string|UploadedFile|null $screenshotE): self {
|
||||
$this->screenshotE = $screenshotE;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getModifiedAt(): ?DateTimeInterface {
|
||||
return $this->modifiedAt;
|
||||
}
|
||||
|
||||
public function setModifiedAt(DateTimeInterface $modifiedAt): self {
|
||||
$this->modifiedAt = $modifiedAt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVersion(): ?float {
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
public function setVersion(float $version): self {
|
||||
$this->version = $version;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsDeleted(): ?bool {
|
||||
return $this->isDeleted;
|
||||
}
|
||||
|
||||
public function setIsDeleted(bool $isDeleted): self {
|
||||
$this->isDeleted = $isDeleted;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
234
src/Entity/Region.php
Normal file
234
src/Entity/Region.php
Normal file
@ -0,0 +1,234 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\RegionRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
#[ORM\Entity(repositoryClass: RegionRepository::class)]
|
||||
#[ORM\Index(columns: ['slug'])]
|
||||
#[UniqueEntity(fields: ['name'], message: 'There is already an region with this name')]
|
||||
#[UniqueEntity(fields: ['slug'], message: 'There is already an region with this slug')]
|
||||
class Region {
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
|
||||
private ?int $id;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'subRegions')]
|
||||
private ?Region $parentRegion;
|
||||
|
||||
#[ORM\OneToMany(mappedBy: 'parentRegion', targetEntity: self::class)]
|
||||
private Collection $subRegions;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, unique: true)]
|
||||
private ?string $name;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, unique: true)]
|
||||
private ?string $slug;
|
||||
|
||||
#[ORM\Column(type: 'boolean', options: ['default' => 0])]
|
||||
private ?bool $isAlias;
|
||||
|
||||
#[ORM\Column(type: 'json', length: 20, nullable: true)]
|
||||
private ?string $anchor;
|
||||
|
||||
#[ORM\Column(type: 'text', nullable: true)]
|
||||
private ?string $description;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50)]
|
||||
private ?string $icon;
|
||||
|
||||
#[ORM\Column(type: 'tinyint', options: ['default' => 0, 'unsigned' => true])]
|
||||
private ?int $gridHeight;
|
||||
|
||||
#[ORM\Column(type: 'tinyint', options: ['default' => 0, 'unsigned' => true])]
|
||||
private ?int $gridWidth;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50)]
|
||||
private ?string $mapBackground;
|
||||
|
||||
#[ORM\Column(type: 'float')]
|
||||
private ?float $version;
|
||||
|
||||
#[ORM\Column(type: 'smallint', options: ['default' => 65535, 'unsigned' => true])]
|
||||
private ?int $sortOrder;
|
||||
|
||||
#[ORM\Column(type: 'boolean', options: ['default' => 1])]
|
||||
private int $isActive;
|
||||
|
||||
#[ORM\ManyToMany(targetEntity: Worldmark::class, mappedBy: 'regions')]
|
||||
private Collection $worldmarks;
|
||||
|
||||
public function __construct() {
|
||||
$this->id = null;
|
||||
$this->mapBackground = null;
|
||||
$this->worldmarks = new ArrayCollection();
|
||||
$this->subRegions = new ArrayCollection();
|
||||
$this->isAlias = 0;
|
||||
$this->isActive = 1;
|
||||
}
|
||||
|
||||
public function __toString(): string {
|
||||
return $this->getName();
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getParentRegion(): ?self {
|
||||
return $this->parentRegion;
|
||||
}
|
||||
|
||||
public function setParentRegion(?self $parentRegion): self {
|
||||
$this->parentRegion = $parentRegion;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSubRegions(): Collection {
|
||||
return $this->subRegions;
|
||||
}
|
||||
|
||||
public function getName(): ?string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): self {
|
||||
$this->name=$name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSlug(): ?string {
|
||||
return $this->slug;
|
||||
}
|
||||
|
||||
public function setSlug(string $slug): self {
|
||||
$this->slug=$slug;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsAlias(): ?bool {
|
||||
return $this->isAlias;
|
||||
}
|
||||
|
||||
public function setIsAlias(bool $isAlias): self {
|
||||
$this->isAlias = $isAlias;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAnchor(): ?string {
|
||||
return $this->anchor;
|
||||
}
|
||||
|
||||
public function setAnchor(?string $anchor): self {
|
||||
$this->anchor = $anchor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(?string $description): self {
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIcon(): ?string {
|
||||
return $this->icon;
|
||||
}
|
||||
|
||||
public function setIcon(string $icon): self {
|
||||
$this->icon=$icon;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getGridHeight(): ?int {
|
||||
return $this->gridHeight;
|
||||
}
|
||||
|
||||
public function setGridHeight(int $gridHeight): self {
|
||||
$this->gridHeight=$gridHeight;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getGridWidth(): ?int {
|
||||
return $this->gridWidth;
|
||||
}
|
||||
|
||||
public function setGridWidth(int $gridWidth): self {
|
||||
$this->gridWidth=$gridWidth;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMapBackground(): ?string {
|
||||
return $this->mapBackground;
|
||||
}
|
||||
|
||||
public function setMapBackground(string $mapBackground): self {
|
||||
$this->mapBackground=$mapBackground;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVersion(): ?float {
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
public function setVersion(float $version): self {
|
||||
$this->version=$version;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSortOrder(): ?int {
|
||||
return $this->sortOrder;
|
||||
}
|
||||
|
||||
public function setSortOrder(int $sortOrder): self {
|
||||
$this->sortOrder=$sortOrder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsActive(): bool {
|
||||
return $this->isActive;
|
||||
}
|
||||
|
||||
public function setIsActive(bool $isActive): self {
|
||||
$this->isActive=$isActive;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getWorldmarks(): Collection {
|
||||
return $this->worldmarks;
|
||||
}
|
||||
|
||||
public function addWorldmark(Worldmark $worldmark): self {
|
||||
if(!$this->worldmarks->contains($worldmark)) {
|
||||
$this->worldmarks[]=$worldmark;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeWorldmark(Worldmark $worldmark): self {
|
||||
$this->worldmarks->removeElement($worldmark);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
138
src/Entity/User.php
Normal file
138
src/Entity/User.php
Normal file
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\UserRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
#[ORM\Entity(repositoryClass: UserRepository::class)]
|
||||
#[ORM\HasLifecycleCallbacks]
|
||||
#[UniqueEntity(fields: ['username'], message: 'There is already an account with this username')]
|
||||
#[UniqueEntity(fields: ['email'], message: 'There is already an account with this email')]
|
||||
class User implements UserInterface, PasswordAuthenticatedUserInterface {
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
|
||||
private $id;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 180, unique: true)]
|
||||
private $username;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 255, nullable: true)]
|
||||
private $email;
|
||||
|
||||
#[ORM\Column(type: 'integer', nullable: true, options: ["unsigned" => true])]
|
||||
private $uid;
|
||||
|
||||
#[ORM\Column(type: 'string')]
|
||||
private $password;
|
||||
|
||||
#[ORM\Column(type: 'json')]
|
||||
private $roles = [];
|
||||
|
||||
public function __toString(): string {
|
||||
return $this->getUserIdentifier();
|
||||
}
|
||||
|
||||
#[ORM\PrePersist]
|
||||
public function setFirstRole() {
|
||||
$this->setRoles(array());
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* A visual identifier that represents this user.
|
||||
*
|
||||
* @see UserInterface
|
||||
*/
|
||||
public function getUserIdentifier(): string {
|
||||
return (string)$this->username;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Symfony 5.3, use getUserIdentifier instead
|
||||
*/
|
||||
public function getUsername(): string {
|
||||
return (string)$this->username;
|
||||
}
|
||||
|
||||
public function setUsername(string $username): self {
|
||||
$this->username = $username;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEmail(): ?string {
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setEmail(?string $email): self {
|
||||
$this->email = $email;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUid(): ?int {
|
||||
return $this->uid;
|
||||
}
|
||||
|
||||
public function setUid(?int $uid): self {
|
||||
$this->uid = $uid;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PasswordAuthenticatedUserInterface
|
||||
*/
|
||||
public function getPassword(): string {
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function setPassword(string $password): self {
|
||||
$this->password = $password;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UserInterface
|
||||
*/
|
||||
public function getRoles(): array {
|
||||
return $this->roles;
|
||||
}
|
||||
|
||||
public function setRoles(array $roles): self {
|
||||
if(!in_array('ROLE_USER', $roles)) {
|
||||
array_unshift($roles, 'ROLE_USER');
|
||||
}
|
||||
|
||||
$this->roles = array_unique($roles);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returning a salt is only needed, if you are not using a modern
|
||||
* hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
|
||||
*
|
||||
* @see UserInterface
|
||||
*/
|
||||
public function getSalt(): ?string {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UserInterface
|
||||
*/
|
||||
public function eraseCredentials() {
|
||||
// If you store any temporary, sensitive data on the user, clear it here
|
||||
// $this->plainPassword = null;
|
||||
}
|
||||
}
|
||||
217
src/Entity/Worldmark.php
Normal file
217
src/Entity/Worldmark.php
Normal file
@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\WorldmarkRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
#[ORM\Entity(repositoryClass: WorldmarkRepository::class)]
|
||||
#[ORM\Index(columns: ['slug'])]
|
||||
#[UniqueEntity(fields: ['slug'], message: 'There is already a worldmark with this slug')]
|
||||
class Worldmark {
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
|
||||
private $id;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: WorldmarkCategory::class)]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
private $category;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Item::class)]
|
||||
private $item;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Monster::class)]
|
||||
private $monster;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 60)]
|
||||
private $name;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 60, unique: true)]
|
||||
private $slug;
|
||||
|
||||
#[ORM\Column(type: 'text', nullable: true)]
|
||||
private $description;
|
||||
|
||||
#[ORM\Column(type: 'tinyint', options: ['default' => 1, 'unsigned' => true])]
|
||||
private $defaultQuantityValue;
|
||||
|
||||
#[ORM\Column(type: 'tinyint', options: ['default' => 0, 'unsigned' => true])]
|
||||
private $defaultPrimogemValue;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, nullable: true)]
|
||||
private $icon;
|
||||
|
||||
#[ORM\Column(type: 'boolean', options: ['default' => 1])]
|
||||
private $canBeHidden;
|
||||
|
||||
#[ORM\Column(type: 'float')]
|
||||
private $version;
|
||||
|
||||
#[ORM\Column(type: 'smallint', options: ['default' => 65535, 'unsigned' => true])]
|
||||
private $sortOrder;
|
||||
|
||||
#[ORM\ManyToMany(targetEntity: Region::class, inversedBy: 'worldmarks')]
|
||||
#[ORM\JoinTable(name: 'region_worldmark')]
|
||||
private $regions;
|
||||
|
||||
public function __construct() {
|
||||
$this->defaultQuantityValue = 1;
|
||||
$this->defaultPrimogemValue = 0;
|
||||
$this->canBeHidden = 1;
|
||||
$this->regions=new ArrayCollection();
|
||||
}
|
||||
|
||||
public function __toString(): string {
|
||||
return $this->getName();
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getCategory(): WorldmarkCategory {
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
public function setCategory(WorldmarkCategory $category): self {
|
||||
$this->category=$category;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getItem(): ?Item {
|
||||
return $this->item;
|
||||
}
|
||||
|
||||
public function setItem(?Item $item): self {
|
||||
$this->item=$item;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMonster(): ?Monster {
|
||||
return $this->monster;
|
||||
}
|
||||
|
||||
public function setMonster(?Monster $monster): self {
|
||||
$this->monster=$monster;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): ?string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): self {
|
||||
$this->name=$name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSlug(): ?string {
|
||||
return $this->slug;
|
||||
}
|
||||
|
||||
public function setSlug(string $slug): self {
|
||||
$this->slug=$slug;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(?string $description): self {
|
||||
$this->description=$description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDefaultQuantityValue() {
|
||||
return $this->defaultQuantityValue;
|
||||
}
|
||||
|
||||
public function setDefaultQuantityValue($defaultQuantityValue): self {
|
||||
$this->defaultQuantityValue = $defaultQuantityValue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDefaultPrimogemValue() {
|
||||
return $this->defaultPrimogemValue;
|
||||
}
|
||||
|
||||
public function setDefaultPrimogemValue($defaultPrimogemValue): self {
|
||||
$this->defaultPrimogemValue = $defaultPrimogemValue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIcon(): string|UploadedFile|null {
|
||||
return $this->icon;
|
||||
}
|
||||
|
||||
public function setIcon(string|UploadedFile|null $icon): self {
|
||||
$this->icon=$icon;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCanBeHidden(): ?bool {
|
||||
return $this->canBeHidden;
|
||||
}
|
||||
|
||||
public function setCanBeHidden(bool $canBeHidden): self {
|
||||
$this->canBeHidden=$canBeHidden;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVersion(): ?float {
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
public function setVersion(float $version): self {
|
||||
$this->version=$version;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSortOrder(): ?int {
|
||||
return $this->sortOrder;
|
||||
}
|
||||
|
||||
public function setSortOrder(int $sortOrder): self {
|
||||
$this->sortOrder=$sortOrder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRegions(): Collection {
|
||||
return $this->regions;
|
||||
}
|
||||
|
||||
public function addRegion(Region $region): self {
|
||||
if(!$this->regions->contains($region)) {
|
||||
$this->regions[]=$region;
|
||||
$region->addWorldmark($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeRegion(Region $region): self {
|
||||
if($this->regions->removeElement($region)) {
|
||||
$region->removeWorldmark($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
65
src/Entity/WorldmarkCategory.php
Normal file
65
src/Entity/WorldmarkCategory.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\WorldmarkCategoryRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
|
||||
#[ORM\Entity(repositoryClass: WorldmarkCategoryRepository::class)]
|
||||
#[ORM\Index(columns: ['slug'])]
|
||||
#[UniqueEntity(fields: ['name'], message: 'There is already a worldmark category with this name')]
|
||||
#[UniqueEntity(fields: ['slug'], message: 'There is already a worldmark category with this slug')]
|
||||
class WorldmarkCategory {
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer', options: ['unsigned' => true])]
|
||||
private $id;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, unique: true)]
|
||||
private $name;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 50, unique: true)]
|
||||
private $slug;
|
||||
|
||||
#[ORM\Column(type: 'smallint', options: ['default' => 65535, 'unsigned' => true])]
|
||||
private $sortOrder;
|
||||
|
||||
public function __toString(): string {
|
||||
return $this->getName();
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getName(): ?string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): self {
|
||||
$this->name=$name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSlug(): ?string {
|
||||
return $this->slug;
|
||||
}
|
||||
|
||||
public function setSlug(string $slug): self {
|
||||
$this->slug=$slug;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSortOrder(): ?int {
|
||||
return $this->sortOrder;
|
||||
}
|
||||
|
||||
public function setSortOrder(int $sortOrder): self {
|
||||
$this->sortOrder=$sortOrder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
79
src/EventListener/KernelListener.php
Normal file
79
src/EventListener/KernelListener.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\EventListener;
|
||||
|
||||
use App\Extension\PhpExtension;
|
||||
use App\Kernel;
|
||||
use App\Repository\RegionRepository;
|
||||
use App\Repository\WorldmarkCategoryRepository;
|
||||
use Detection\MobileDetect;
|
||||
use Symfony\Component\HttpKernel\Event\ControllerEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Twig\Environment as TwigEnvironment;
|
||||
|
||||
class KernelListener {
|
||||
public function __construct(private Security $security,
|
||||
private RouterInterface $router,
|
||||
private TwigEnvironment $twigEnvironment,
|
||||
private PhpExtension $phpExtension,
|
||||
// private MobileDetect $mobileDetect,
|
||||
private RegionRepository $regionRepository,
|
||||
private WorldmarkCategoryRepository $worldmarkCategoryRepository) {}
|
||||
|
||||
public function onKernelRequest(RequestEvent $requestEvent) {
|
||||
$request=$requestEvent->getRequest();
|
||||
|
||||
if(!$requestEvent->isMainRequest() || $request->isXmlHttpRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(($this->phpExtension->strStartWith($request->attributes->get('_route'), 'bo_')
|
||||
&& !$this->security->isGranted('ROLE_CONTRIBUTOR'))
|
||||
|| ($this->phpExtension->strStartWith($request->getRequestUri(), '/dev')
|
||||
&& (!$this->security->getUser() || !$this->security->isGranted('ROLE_ADMIN')))) {
|
||||
|
||||
throw new NotFoundHttpException("Page not found");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function onKernelController(ControllerEvent $controllerEvent) {
|
||||
if(!$controllerEvent->isMainRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request = $controllerEvent->getRequest();
|
||||
|
||||
$route = $request->attributes->get('_route');
|
||||
|
||||
$this->twigEnvironment->addGlobal('user', $this->security->getUser());
|
||||
$this->twigEnvironment->addGlobal('route', $route);
|
||||
$this->twigEnvironment->addGlobal('locale', $request->getLocale());
|
||||
$this->twigEnvironment->addGlobal('gameVersion', Kernel::GAME_VERSION);
|
||||
$this->twigEnvironment->addGlobal('supportedGameVersion', Kernel::SUPPORTED_GAME_VERSION);
|
||||
$this->twigEnvironment->addGlobal('isTouchDevice', $this->isTouchDevice());
|
||||
|
||||
$regions = $this->regionRepository->getRegions();
|
||||
$this->twigEnvironment->addGlobal('regions', $regions);
|
||||
}
|
||||
|
||||
public function onKernelResponse(ResponseEvent $responseEvent) {
|
||||
}
|
||||
|
||||
public function onKernelException(ExceptionEvent $exceptionEvent) {
|
||||
}
|
||||
|
||||
private function isTouchDevice(): array {
|
||||
$detect = new MobileDetect();
|
||||
|
||||
return array(
|
||||
'isTablet' => $detect->isTablet(),
|
||||
'isMobile' => $detect->isMobile(),
|
||||
);
|
||||
}
|
||||
}
|
||||
49
src/Extension/PhpExtension.php
Normal file
49
src/Extension/PhpExtension.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Extension;
|
||||
|
||||
class PhpExtension {
|
||||
public function strStartWith(string $str, string $needle): bool {
|
||||
if($str === '' || $needle === '' || strlen($needle) > strlen($str) || substr_compare($str, $needle, 0, strlen($needle)) !== 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function strEndWith(string $str, string $needle): bool {
|
||||
if($str === '' || $needle === '' || strlen($needle) > strlen($str) || substr_compare($str, $needle, strlen($str)-strlen($needle), strlen($needle)) !== 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function strLike(string $str, string $needle, bool $ignoreCase = false): bool {
|
||||
if($ignoreCase) {
|
||||
return str_contains(strtolower($str), strtolower($needle));
|
||||
} else {
|
||||
return str_contains($str, $needle);
|
||||
}
|
||||
}
|
||||
|
||||
public function strPad(string $str, int $padLength, string $padString, string $direction='left'): string {
|
||||
$strPad=null;
|
||||
if($direction == 'left') {
|
||||
$strPad=STR_PAD_LEFT;
|
||||
} elseif($direction == 'right') {
|
||||
$strPad=STR_PAD_RIGHT;
|
||||
} elseif($direction == 'both') {
|
||||
$strPad=STR_PAD_BOTH;
|
||||
}
|
||||
if($strPad !== null) {
|
||||
return str_pad($str, $padLength, $padString, $strPad);
|
||||
} else {
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
|
||||
public function trim($input): array|string {
|
||||
return !is_array($input) ? trim($input) : array_map(array($this, 'trim',), $input);
|
||||
}
|
||||
}
|
||||
105
src/Extension/TwigExtension.php
Normal file
105
src/Extension/TwigExtension.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace App\Extension;
|
||||
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
class TwigExtension extends AbstractExtension {
|
||||
public function getFunctions(): array {
|
||||
return array(
|
||||
new TwigFunction('getUuid', array($this, 'getUuidFunction')),
|
||||
);
|
||||
}
|
||||
|
||||
public function getFilters(): array {
|
||||
return array(
|
||||
new TwigFilter('json_decode', array($this, 'jsonDecodeFilter')),
|
||||
new TwigFilter('start_with', array($this, 'strStartWithFilter')),
|
||||
new TwigFilter('end_with', array($this, 'strEndWithFilter')),
|
||||
new TwigFilter('like', array($this, 'strLikeFilter')),
|
||||
new TwigFilter('pad', array($this, 'strPadFilter')),
|
||||
new TwigFilter('trim', array($this, 'trimFilter')),
|
||||
new TwigFilter('shuffle_array', array($this, 'shuffleArrayFilter')),
|
||||
);
|
||||
}
|
||||
|
||||
//<editor-fold desc="TWIG FUNCTIONS">
|
||||
public function getUuidFunction(): string {
|
||||
return Uuid::uuid1()->toString();
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
//<editor-fold desc="TWIG FILTERS">
|
||||
public function jsonDecodeFilter($json): mixed {
|
||||
if($this->isJson($json)) {
|
||||
return json_decode($json);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function strStartWithFilter(string $str, string $needle): bool {
|
||||
if($str === '' || $needle === '' || strlen($needle) > strlen($str) || substr_compare($str, $needle, 0, strlen($needle)) !== 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function strEndWithFilter(string $str, string $needle): bool {
|
||||
if($str === '' || $needle === '' || strlen($needle) > strlen($str) || substr_compare($str, $needle, strlen($str) - strlen($needle), strlen($needle)) !== 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function strLikeFilter(string $str, string $needle, bool $ignoreCase = false): bool {
|
||||
if($ignoreCase) {
|
||||
return str_contains(strtolower($str), strtolower($needle));
|
||||
} else {
|
||||
return str_contains($str, $needle);
|
||||
}
|
||||
}
|
||||
|
||||
public function strPadFilter(string $str, int $padLength, string $padString, string $direction = 'left'): string {
|
||||
$strPad = null;
|
||||
if($direction == 'left') {
|
||||
$strPad = STR_PAD_LEFT;
|
||||
} elseif($direction == 'right') {
|
||||
$strPad = STR_PAD_RIGHT;
|
||||
} elseif($direction == 'both') {
|
||||
$strPad = STR_PAD_BOTH;
|
||||
}
|
||||
if($strPad !== null) {
|
||||
return str_pad($str, $padLength, $padString, $strPad);
|
||||
} else {
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
|
||||
public function trimFilter($input): array|string {
|
||||
return !is_array($input) ? trim($input) : array_map(array($this, 'trim',), $input);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
* @return array
|
||||
*/
|
||||
public function shuffleArrayFilter(array $array): array {
|
||||
shuffle($array);
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
//</editor-fold>
|
||||
|
||||
private function isJson($string): bool {
|
||||
json_decode($string);
|
||||
|
||||
return (json_last_error() == JSON_ERROR_NONE);
|
||||
}
|
||||
}
|
||||
37
src/Form/GridType.php
Normal file
37
src/Form/GridType.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Grid;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class GridType extends AbstractType {
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void {
|
||||
// $builder->add('row')
|
||||
// ->add('col')
|
||||
// ->add('region');
|
||||
$builder->add('positions', ChoiceType::class, array(
|
||||
'choices' => array(
|
||||
'Add row before' => 'row_before',
|
||||
'Add row after' => 'row_after',
|
||||
'Add column before' => 'column_before',
|
||||
'Add column after' => 'column_after',
|
||||
),
|
||||
'data'=>null,
|
||||
'mapped'=>false,
|
||||
'expanded'=>true,
|
||||
'multiple'=>true,
|
||||
'required'=>false,
|
||||
));
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void {
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => Grid::class,
|
||||
'data_route' => null,
|
||||
));
|
||||
}
|
||||
}
|
||||
33
src/Form/ItemCategoryType.php
Normal file
33
src/Form/ItemCategoryType.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\ItemCategory;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class ItemCategoryType extends AbstractType {
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void {
|
||||
$builder->add('name', TextType::class, array(
|
||||
'attr' => array('data-slug-target' => 'item_category_name')
|
||||
))
|
||||
->add('slug', TextType::class, array(
|
||||
'attr' => array(
|
||||
'data-slug-source' => 'item_category_name',
|
||||
'readonly' => 'readonly',
|
||||
),
|
||||
))
|
||||
->add('sortOrder', TextType::class, array(
|
||||
// 'attr' => array('pattern'=>'^([1-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$'),
|
||||
));
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void {
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => ItemCategory::class,
|
||||
'data_route' => null,
|
||||
));
|
||||
}
|
||||
}
|
||||
56
src/Form/ItemType.php
Normal file
56
src/Form/ItemType.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Item;
|
||||
use App\Extension\PhpExtension;
|
||||
use App\Kernel;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class ItemType extends AbstractType {
|
||||
public function __construct(private PhpExtension $phpExtension) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void {
|
||||
$builder->add('name', TextType::class, array(
|
||||
'attr'=>array('data-slug-target'=>'item_name')
|
||||
))
|
||||
->add('slug', TextType::class, array(
|
||||
'attr'=>array(
|
||||
'data-slug-source'=>'item_name',
|
||||
'readonly'=>'readonly'
|
||||
)
|
||||
))
|
||||
->add('description', TextareaType::class, array(
|
||||
'required'=>false
|
||||
))
|
||||
->add('icon', FileType::class, array(
|
||||
'data'=>null,
|
||||
'required'=>false,
|
||||
))
|
||||
->add('version', ChoiceType::class, array(
|
||||
'choices'=>array_combine(Kernel::SUPPORTED_GAME_VERSION, Kernel::SUPPORTED_GAME_VERSION),
|
||||
'data'=>$this->phpExtension->strEndWith($options['data_route'], '_new') ? Kernel::GAME_VERSION : $options['data']->getVersion(),
|
||||
));
|
||||
|
||||
if($this->phpExtension->strEndWith($options['data_route'], '_edit')) {
|
||||
$builder->add('removeFile', CheckboxType::class, array(
|
||||
'mapped'=>false,
|
||||
'required'=>false,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void {
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => Item::class,
|
||||
'data_route' => null,
|
||||
));
|
||||
}
|
||||
}
|
||||
51
src/Form/MapFragmentType.php
Normal file
51
src/Form/MapFragmentType.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Map;
|
||||
use App\Extension\PhpExtension;
|
||||
use App\Kernel;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class MapFragmentType extends AbstractType {
|
||||
public function __construct(private PhpExtension $phpExtension) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void {
|
||||
$builder->add('row', TextType::class, array(
|
||||
'attr'=>array('pattern'=>'[0-9]'),
|
||||
))
|
||||
->add('col', TextType::class, array(
|
||||
'attr'=>array('pattern'=>'[0-9]'),
|
||||
))
|
||||
->add('fragment', FileType::class, array(
|
||||
'data_class'=>null,
|
||||
'required'=>false,
|
||||
))
|
||||
->add('version', ChoiceType::class, array(
|
||||
'choices'=>array_combine(Kernel::SUPPORTED_GAME_VERSION, Kernel::SUPPORTED_GAME_VERSION),
|
||||
'data'=>$this->phpExtension->strEndWith($options['data_route'], '_new') ? Kernel::GAME_VERSION : $options['data']->getVersion(),
|
||||
));
|
||||
// ->add('modifiedAt')
|
||||
// ->add('region');
|
||||
|
||||
if($this->phpExtension->strEndWith($options['data_route'], '_edit')) {
|
||||
$builder->add('blank', CheckboxType::class, array(
|
||||
'mapped'=>false,
|
||||
'required'=>false,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void {
|
||||
$resolver->setDefaults([
|
||||
'data_class'=>Map::class,
|
||||
'data_route'=>null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
33
src/Form/MapType.php
Normal file
33
src/Form/MapType.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Map;
|
||||
use App\Extension\PhpExtension;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class MapType extends AbstractType {
|
||||
public function __construct(private PhpExtension $phpExtension) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void {
|
||||
$builder->add('file', FileType::class, array(
|
||||
'data_class'=>null,
|
||||
'required'=>false,
|
||||
));
|
||||
|
||||
if($this->phpExtension->strEndWith($options['data_route'], '_new')) {
|
||||
$builder->add('version', HiddenType::class);
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void {
|
||||
$resolver->setDefaults(array(
|
||||
'data_class'=>Map::class,
|
||||
'data_route'=>null,
|
||||
));
|
||||
}
|
||||
}
|
||||
30
src/Form/MonsterCategoryType.php
Normal file
30
src/Form/MonsterCategoryType.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\MonsterCategory;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class MonsterCategoryType extends AbstractType {
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void {
|
||||
$builder->add('name', TextType::class, array(
|
||||
'attr'=>array('data-slug-target'=>'monster_category_name')
|
||||
))
|
||||
->add('slug', TextType::class, array(
|
||||
'attr'=>array(
|
||||
'data-slug-source'=>'monster_category_name',
|
||||
'readonly'=>'readonly'
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void {
|
||||
$resolver->setDefaults(array(
|
||||
'data_class'=>MonsterCategory::class,
|
||||
'data_route'=>null,
|
||||
));
|
||||
}
|
||||
}
|
||||
58
src/Form/MonsterType.php
Normal file
58
src/Form/MonsterType.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Monster;
|
||||
use App\Extension\PhpExtension;
|
||||
use App\Kernel;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class MonsterType extends AbstractType {
|
||||
public function __construct(private PhpExtension $phpExtension) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void {
|
||||
$builder->add('name', TextType::class, array(
|
||||
'attr'=>array(
|
||||
'data-slug-target'=>'monster_name'
|
||||
)
|
||||
))
|
||||
->add('slug', TextType::class, array(
|
||||
'attr'=>array(
|
||||
'data-slug-source'=>'monster_name',
|
||||
'readonly'=>'readonly'
|
||||
)
|
||||
))
|
||||
->add('description', TextareaType::class, array(
|
||||
'required'=>false
|
||||
))
|
||||
->add('icon', FileType::class, array(
|
||||
'data'=>null,
|
||||
'required'=>false,
|
||||
))
|
||||
->add('version', ChoiceType::class, array(
|
||||
'choices'=>array_combine(Kernel::SUPPORTED_GAME_VERSION, Kernel::SUPPORTED_GAME_VERSION),
|
||||
'data'=>$this->phpExtension->strEndWith($options['data_route'], '_new') ? Kernel::GAME_VERSION : $options['data']->getVersion(),
|
||||
));
|
||||
|
||||
if($this->phpExtension->strEndWith($options['data_route'], '_edit')) {
|
||||
$builder->add('removeFile', CheckboxType::class, array(
|
||||
'mapped'=>false,
|
||||
'required'=>false,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void {
|
||||
$resolver->setDefaults(array(
|
||||
'data_class'=>Monster::class,
|
||||
'data_route'=>null,
|
||||
));
|
||||
}
|
||||
}
|
||||
126
src/Form/NodeType.php
Normal file
126
src/Form/NodeType.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Node;
|
||||
use App\Extension\PhpExtension;
|
||||
use App\Kernel;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\CallbackTransformer;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class NodeType extends AbstractType {
|
||||
public function __construct(private PhpExtension $phpExtension) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void {
|
||||
/** @var Node $node */
|
||||
$node =$options['data'];
|
||||
|
||||
|
||||
if($options['data_route'] == 'bo_node_delete') {
|
||||
$builder->add('isDeleted', HiddenType::class, array(
|
||||
'data'=>true,
|
||||
'required'=>true
|
||||
));
|
||||
} else {
|
||||
$coordinate = $node->getCoordinate();
|
||||
$versions=Kernel::SUPPORTED_GAME_VERSION;
|
||||
|
||||
foreach($versions as $key=>$version) {
|
||||
if($version < Kernel::GAME_VERSION) {
|
||||
unset($versions[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$builder->add('quantity', TextType::class, array(
|
||||
'attr'=>array(
|
||||
'pattern'=>'^([1-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$',
|
||||
),
|
||||
'data' => $this->phpExtension->strEndWith($options['data_route'], '_new') ? $node->getWorldmark()->getDefaultQuantityValue() : $node->getQuantity()
|
||||
))
|
||||
->add('primogem', TextType::class, array(
|
||||
'attr'=>array(
|
||||
'pattern'=>'^([0-9]|[1-9][0-9]{1-2})$',
|
||||
),
|
||||
'data' => $this->phpExtension->strEndWith($options['data_route'], '_new') ? $node->getWorldmark()->getDefaultPrimogemValue() : $node->getPrimogem()
|
||||
))
|
||||
->add('coordinate', HiddenType::class)
|
||||
->add('coordX', NumberType::class, array(
|
||||
'attr'=>array(
|
||||
'readonly'=>true,
|
||||
'disabled'=>true,
|
||||
),
|
||||
'data'=>$coordinate['x'],
|
||||
'mapped'=>false,
|
||||
))
|
||||
->add('coordY', NumberType::class, array(
|
||||
'attr'=>array(
|
||||
'readonly'=>true,
|
||||
'disabled'=>true,
|
||||
),
|
||||
'data'=>$coordinate['y'],
|
||||
'mapped'=>false,
|
||||
))
|
||||
->add('description', TextareaType::class, array(
|
||||
'required'=>false
|
||||
))
|
||||
->add('screenshotA', FileType::class, array(
|
||||
'data'=>null,
|
||||
'required'=>false,
|
||||
))
|
||||
->add('screenshotB', FileType::class, array(
|
||||
'data'=>null,
|
||||
'required'=>false,
|
||||
))
|
||||
->add('screenshotC', FileType::class, array(
|
||||
'data'=>null,
|
||||
'required'=>false,
|
||||
))
|
||||
->add('screenshotD', FileType::class, array(
|
||||
'data'=>null,
|
||||
'required'=>false,
|
||||
))
|
||||
->add('screenshotE', FileType::class, array(
|
||||
'data'=>null,
|
||||
'required'=>false,
|
||||
))
|
||||
->add('version', ChoiceType::class, array(
|
||||
'choices' => array_combine($versions, $versions),
|
||||
'data' => $this->phpExtension->strEndWith($options['data_route'], '_new') ? Kernel::GAME_VERSION : ($options['data']->getVersion() < Kernel::GAME_VERSION ? Kernel::GAME_VERSION : $options['data']->getVersion()),
|
||||
'expanded' => true,
|
||||
'multiple' => false,
|
||||
'required' => true,
|
||||
));
|
||||
// ->add('createAt')
|
||||
// ->add('modifiedAt')
|
||||
|
||||
// ->add('isDeleted')
|
||||
// ->add('grid')
|
||||
// ->add('worldmark')
|
||||
|
||||
$builder->get('coordinate')
|
||||
->addModelTransformer(new CallbackTransformer(
|
||||
function($array) use ($builder) {
|
||||
return json_encode($array);
|
||||
},
|
||||
function($string) use ($builder) {
|
||||
return json_decode($string, true);
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void {
|
||||
$resolver->setDefaults(array(
|
||||
'data_class'=>Node::class,
|
||||
'data_route'=>null,
|
||||
));
|
||||
}
|
||||
}
|
||||
107
src/Form/RegionType.php
Normal file
107
src/Form/RegionType.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Region;
|
||||
use App\Extension\PhpExtension;
|
||||
use App\Kernel;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class RegionType extends AbstractType {
|
||||
private array $parameters;
|
||||
|
||||
public function __construct(ParameterBagInterface $parameterBag,
|
||||
private PhpExtension $phpExtension) {
|
||||
$this->parameters=array('assets'=>$parameterBag->get('assets'));
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void {
|
||||
$icons=array();
|
||||
$finder=new Finder();
|
||||
$finder->files()->in($this->parameters['assets']['img']['region'])
|
||||
->name('*.png')
|
||||
->sortByName();
|
||||
|
||||
foreach($finder as $fileInfo) {
|
||||
$icons[$fileInfo->getBasename()]=$fileInfo->getBasename();
|
||||
}
|
||||
|
||||
$builder->add('parentRegion')
|
||||
->add('name', TextType::class, array(
|
||||
'attr'=>array(
|
||||
'data-slug-target'=>'region_name'
|
||||
)
|
||||
))
|
||||
->add('slug', TextType::class, array(
|
||||
'attr'=>array(
|
||||
'data-slug-source'=>'region_name',
|
||||
'readonly'=>'readonly'
|
||||
)
|
||||
))
|
||||
->add('isAlias', ChoiceType::class, array(
|
||||
'choices'=>array('No'=>0, 'Yes'=>1),
|
||||
'data'=>$this->phpExtension->strEndWith($options['data_route'], '_new') ? 0 : $options['data']->getIsAlias(),
|
||||
'expanded' => true,
|
||||
'multiple' => false,
|
||||
'required' => true,
|
||||
))
|
||||
->add('anchor', TextType::class, array('required' => false))
|
||||
->add('description', TextareaType::class, array(
|
||||
'required'=>false
|
||||
))
|
||||
->add('icon', ChoiceType::class, array(
|
||||
'choices'=>$icons,
|
||||
'expanded'=>true,
|
||||
'required'=>true,
|
||||
))
|
||||
->add('mapBackground', ChoiceType::class, array(
|
||||
'choices' => array(
|
||||
'Sea' => 'sea',
|
||||
'Sand' => 'sand',
|
||||
),
|
||||
'expanded'=>true,
|
||||
'required' => true,
|
||||
))
|
||||
->add('version', ChoiceType::class, array(
|
||||
'choices'=>array_combine(Kernel::SUPPORTED_GAME_VERSION, Kernel::SUPPORTED_GAME_VERSION),
|
||||
'data'=>$this->phpExtension->strEndWith($options['data_route'], '_new') ? Kernel::GAME_VERSION : $options['data']->getVersion(),
|
||||
))
|
||||
->add('sortOrder', TextType::class, array(
|
||||
// 'attr'=>array('pattern'=>'^([1-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$'),
|
||||
))
|
||||
->add('isActive', ChoiceType::class, array(
|
||||
'choices'=>array('No'=>0, 'Yes'=>1),
|
||||
'data'=>$this->phpExtension->strEndWith($options['data_route'], '_new') ? 1 : $options['data']->getIsActive(),
|
||||
'expanded' => true,
|
||||
'multiple' => false,
|
||||
'required' => true,
|
||||
));
|
||||
|
||||
if($this->phpExtension->strEndWith($options['data_route'], '_new')) {
|
||||
$builder->add('gridHeight', TextType::class, array(
|
||||
'attr'=>array(
|
||||
'pattern'=>'^([1-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$',
|
||||
),
|
||||
))
|
||||
->add('gridWidth', TextType::class, array(
|
||||
'attr'=>array(
|
||||
'pattern'=>'^([1-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$',
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void {
|
||||
$resolver->setDefaults(array(
|
||||
'data_class'=>Region::class,
|
||||
'data_route'=>null,
|
||||
));
|
||||
}
|
||||
}
|
||||
48
src/Form/SecurityType.php
Normal file
48
src/Form/SecurityType.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\User;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\IsTrue;
|
||||
use Symfony\Component\Validator\Constraints\Length;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
|
||||
class SecurityType extends AbstractType {
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void {
|
||||
$builder->add('username')
|
||||
->add('plainPassword', PasswordType::class, array(
|
||||
// instead of being set onto the object directly,
|
||||
// this is read and encoded in the controller
|
||||
'mapped' => false,
|
||||
'attr' => array('autocomplete' => 'new-password'),
|
||||
'constraints' => array(
|
||||
new NotBlank(array('message' => 'Please enter a password')),
|
||||
new Length(array(
|
||||
'min' => 6,
|
||||
'minMessage' => 'Your password should be at least {{ limit }} characters',
|
||||
// max length allowed by Symfony for security reasons
|
||||
'max' => 4096,
|
||||
)),
|
||||
),
|
||||
))
|
||||
->add('agreeTerms', CheckboxType::class, array(
|
||||
'mapped' => false,
|
||||
'constraints' => array(
|
||||
new IsTrue(array('message' => 'You should agree to our terms.')),
|
||||
),
|
||||
'label' => 'Agree non-existing terms',
|
||||
));
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void {
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => User::class,
|
||||
'data_route' => null,
|
||||
));
|
||||
}
|
||||
}
|
||||
33
src/Form/WorldmarkCategoryType.php
Normal file
33
src/Form/WorldmarkCategoryType.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\WorldmarkCategory;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class WorldmarkCategoryType extends AbstractType {
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void {
|
||||
$builder->add('name', TextType::class, array(
|
||||
'attr' => array('data-slug-target' => 'worldmark_category_name'),
|
||||
))
|
||||
->add('slug', TextType::class, array(
|
||||
'attr' => array(
|
||||
'data-slug-source' => 'worldmark_category_name',
|
||||
'readonly' => 'readonly',
|
||||
),
|
||||
))
|
||||
->add('sortOrder', TextType::class, array(
|
||||
// 'attr' => array('pattern'=>'^([1-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$'),
|
||||
));
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void {
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => WorldmarkCategory::class,
|
||||
'data_route' => null,
|
||||
));
|
||||
}
|
||||
}
|
||||
103
src/Form/WorldmarkType.php
Normal file
103
src/Form/WorldmarkType.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Item;
|
||||
use App\Entity\Monster;
|
||||
use App\Entity\Region;
|
||||
use App\Entity\Worldmark;
|
||||
use App\Extension\PhpExtension;
|
||||
use App\Kernel;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class WorldmarkType extends AbstractType {
|
||||
public function __construct(private PhpExtension $phpExtension) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void {
|
||||
$builder->add('name', TextType::class, array(
|
||||
'attr' => array('data-slug-target' => 'worldmark_name'),
|
||||
))
|
||||
->add('slug', TextType::class, array(
|
||||
'attr' => array(
|
||||
'data-slug-source' => 'worldmark_name',
|
||||
// 'readonly' => 'readonly',
|
||||
),
|
||||
))
|
||||
->add('description', TextareaType::class, array(
|
||||
'required' => false,
|
||||
))
|
||||
->add('defaultQuantityValue', TextType::class, array(
|
||||
'attr' => array(
|
||||
'pattern' => '^([1-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$',
|
||||
),
|
||||
))
|
||||
->add('defaultPrimogemValue', TextType::class, array(
|
||||
'attr' => array(
|
||||
'pattern' => '^([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$',
|
||||
),
|
||||
))
|
||||
->add('icon', FileType::class, array(
|
||||
'data' => null,
|
||||
'required' => false,
|
||||
))
|
||||
->add('canBeHidden')
|
||||
->add('item', EntityType::class, array(
|
||||
'class' => Item::class,
|
||||
'query_builder' => function(EntityRepository $er) {
|
||||
$qb = $er->createQueryBuilder("item");
|
||||
|
||||
return $qb->addSelect("category")
|
||||
->join("item.category", "category")
|
||||
->orderBy("category.name")
|
||||
->addOrderBy("item.name");
|
||||
},
|
||||
'group_by' => 'category',
|
||||
'required' => false,
|
||||
))
|
||||
->add('monster', EntityType::class, array(
|
||||
'class' => Monster::class,
|
||||
'query_builder' => function(EntityRepository $er) {
|
||||
$qb = $er->createQueryBuilder("monster");
|
||||
|
||||
return $qb->addSelect("category")
|
||||
->join("monster.category", "category")
|
||||
->orderBy("category.name")
|
||||
->addOrderBy("monster.name");
|
||||
},
|
||||
'group_by' => 'category',
|
||||
'required' => false,
|
||||
))
|
||||
->add('regions', EntityType::class, array(
|
||||
'class' => Region::class,
|
||||
'query_builder' => function(EntityRepository $er) {
|
||||
$qb = $er->createQueryBuilder("regions");
|
||||
|
||||
return $qb->andWhere($qb->expr()->eq("regions.isActive", 1));
|
||||
},
|
||||
'expanded' => true,
|
||||
'multiple' => true,
|
||||
))
|
||||
->add('version', ChoiceType::class, array(
|
||||
'choices' => array_combine(Kernel::SUPPORTED_GAME_VERSION, Kernel::SUPPORTED_GAME_VERSION),
|
||||
'data' => $this->phpExtension->strEndWith($options['data_route'], '_new') ? Kernel::GAME_VERSION : $options['data']->getVersion(),
|
||||
))
|
||||
->add('sortOrder', TextType::class, array(
|
||||
// 'attr'=>array('pattern'=>'^([1-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$'),
|
||||
));
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void {
|
||||
$resolver->setDefaults(array(
|
||||
'data_class'=>Worldmark::class,
|
||||
'data_route'=>null,
|
||||
));
|
||||
}
|
||||
}
|
||||
17
src/Kernel.php
Normal file
17
src/Kernel.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
|
||||
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
|
||||
|
||||
class Kernel extends BaseKernel {
|
||||
use MicroKernelTrait;
|
||||
|
||||
public const GAME_VERSION = 3.6;
|
||||
public const SUPPORTED_GAME_VERSION=array(
|
||||
1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6,
|
||||
2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8,
|
||||
3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6
|
||||
);
|
||||
}
|
||||
0
src/Repository/.gitignore
vendored
Normal file
0
src/Repository/.gitignore
vendored
Normal file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user