feat: initialisation du projet

- Ajout des dépendances dans `composer.json` (Doctrine, Twig, Security, etc.).
- Configuration de l’environnement de développement via `.env`.
- Mise en place d’un modèle de base pour les assets avec `app.js` et `app.css`.
- Création du fichier de configuration `asset_mapper.yaml`.
- Ajout de la configuration Docker via `compose.yaml` (PostgreSQL, Mailer).
- Ajout des fichiers de base pour les templates Twig (`base.html.twig`).
- Mise à jour des ignores dans le fichier `.gitignore`.
- Fichiers supplémentaires pour le cache, les tests et les bootstrap Symfony.
This commit is contained in:
MLeveque committed 2026-02-22 19:23:55 +01:00
commit c139d6bb1c
53 files changed
+12691

No files matched your search

+18
View File
@@ -0,0 +1,18 @@
###> symfony/framework-bundle ###
APP_ENV=dev
APP_SECRET=
APP_SHARE_DIR=var/share
APP_VERSION=0.0.1
###< symfony/framework-bundle ###
###> doctrine/doctrine-bundle ###
DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"
###< doctrine/doctrine-bundle ###
###> symfony/mailer ###
MAILER_DSN="smtp://localhost:1025"
###< symfony/mailer ###
###> symfony/routing ###
DEFAULT_URI="http://localhost:8000"
###< symfony/routing ###
+28
View File
@@ -0,0 +1,28 @@
### Symfony ###
/vendor/
/var/
/public/bundles/
/public/build/
/config/secrets/
/config/jwt/
/.env.dev
/.env.local
/.env.local.php
/.env.*.local
/.phpunit.result.cache
### PHP ###
.php_cs
.php-cs-fixer.dist.php
.php-cs-fixer.cache
phpunit.xml
.phpunit.result.cache
### PhpStorm ###
.idea/
*.iml
*.iws
### OS / Misc ###
.DS_Store
Thumbs.db
+10
View File
@@ -0,0 +1,10 @@
import './stimulus_bootstrap.js';
/*
* Welcome to your app's main JavaScript file!
*
* This file will be included onto the page via the importmap() Twig function,
* which should already be in your base.html.twig.
*/
import './styles/app.css';
console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉');
+15
View File
@@ -0,0 +1,15 @@
{
"controllers": {
"@symfony/ux-turbo": {
"turbo-core": {
"enabled": true,
"fetch": "eager"
},
"mercure-turbo-stream": {
"enabled": false,
"fetch": "eager"
}
}
},
"entrypoints": []
}
@@ -0,0 +1,81 @@
const nameCheck = /^[-_a-zA-Z0-9]{4,22}$/;
const tokenCheck = /^[-_/+a-zA-Z0-9]{24,}$/;
// Generate and double-submit a CSRF token in a form field and a cookie, as defined by Symfony's SameOriginCsrfTokenManager
// Use `form.requestSubmit()` to ensure that the submit event is triggered. Using `form.submit()` will not trigger the event
// and thus this event-listener will not be executed.
document.addEventListener('submit', function (event) {
generateCsrfToken(event.target);
}, true);
// When @hotwired/turbo handles form submissions, send the CSRF token in a header in addition to a cookie
// The `framework.csrf_protection.check_header` config option needs to be enabled for the header to be checked
document.addEventListener('turbo:submit-start', function (event) {
const h = generateCsrfHeaders(event.detail.formSubmission.formElement);
Object.keys(h).map(function (k) {
event.detail.formSubmission.fetchRequest.headers[k] = h[k];
});
});
// When @hotwired/turbo handles form submissions, remove the CSRF cookie once a form has been submitted
document.addEventListener('turbo:submit-end', function (event) {
removeCsrfToken(event.detail.formSubmission.formElement);
});
export function generateCsrfToken (formElement) {
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
if (!csrfField) {
return;
}
let csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
let csrfToken = csrfField.value;
if (!csrfCookie && nameCheck.test(csrfToken)) {
csrfField.setAttribute('data-csrf-protection-cookie-value', csrfCookie = csrfToken);
csrfField.defaultValue = csrfToken = btoa(String.fromCharCode.apply(null, (window.crypto || window.msCrypto).getRandomValues(new Uint8Array(18))));
}
csrfField.dispatchEvent(new Event('change', { bubbles: true }));
if (csrfCookie && tokenCheck.test(csrfToken)) {
const cookie = csrfCookie + '_' + csrfToken + '=' + csrfCookie + '; path=/; samesite=strict';
document.cookie = window.location.protocol === 'https:' ? '__Host-' + cookie + '; secure' : cookie;
}
}
export function generateCsrfHeaders (formElement) {
const headers = {};
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
if (!csrfField) {
return headers;
}
const csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
if (tokenCheck.test(csrfField.value) && nameCheck.test(csrfCookie)) {
headers[csrfCookie] = csrfField.value;
}
return headers;
}
export function removeCsrfToken (formElement) {
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
if (!csrfField) {
return;
}
const csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
if (tokenCheck.test(csrfField.value) && nameCheck.test(csrfCookie)) {
const cookie = csrfCookie + '_' + csrfField.value + '=0; path=/; samesite=strict; max-age=0';
document.cookie = window.location.protocol === 'https:' ? '__Host-' + cookie + '; secure' : cookie;
}
}
/* stimulusFetch: 'lazy' */
export default 'csrf-protection-controller';
+16
View File
@@ -0,0 +1,16 @@
import { Controller } from '@hotwired/stimulus';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="hello" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* hello_controller.js -> "hello"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
}
}
+5
View File
@@ -0,0 +1,5 @@
import { startStimulusApp } from '@symfony/stimulus-bundle';
startStimulusApp();
// register any custom, 3rd party controllers here
// app.register('some_controller_name', SomeImportedController);
+3
View File
@@ -0,0 +1,3 @@
body {
background-color: skyblue;
}
+7
View File
@@ -0,0 +1,7 @@
/**
* Bundled by jsDelivr using Rollup v2.79.2 and Terser v5.39.0.
* Original file: /npm/@hotwired/stimulus@3.2.2/dist/stimulus.js
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
class e{constructor(e,t,s){this.eventTarget=e,this.eventName=t,this.eventOptions=s,this.unorderedBindings=new Set}connect(){this.eventTarget.addEventListener(this.eventName,this,this.eventOptions)}disconnect(){this.eventTarget.removeEventListener(this.eventName,this,this.eventOptions)}bindingConnected(e){this.unorderedBindings.add(e)}bindingDisconnected(e){this.unorderedBindings.delete(e)}handleEvent(e){const t=function(e){if("immediatePropagationStopped"in e)return e;{const{stopImmediatePropagation:t}=e;return Object.assign(e,{immediatePropagationStopped:!1,stopImmediatePropagation(){this.immediatePropagationStopped=!0,t.call(this)}})}}(e);for(const e of this.bindings){if(t.immediatePropagationStopped)break;e.handleEvent(t)}}hasBindings(){return this.unorderedBindings.size>0}get bindings(){return Array.from(this.unorderedBindings).sort(((e,t)=>{const s=e.index,r=t.index;return s<r?-1:s>r?1:0}))}}class t{constructor(e){this.application=e,this.eventListenerMaps=new Map,this.started=!1}start(){this.started||(this.started=!0,this.eventListeners.forEach((e=>e.connect())))}stop(){this.started&&(this.started=!1,this.eventListeners.forEach((e=>e.disconnect())))}get eventListeners(){return Array.from(this.eventListenerMaps.values()).reduce(((e,t)=>e.concat(Array.from(t.values()))),[])}bindingConnected(e){this.fetchEventListenerForBinding(e).bindingConnected(e)}bindingDisconnected(e,t=!1){this.fetchEventListenerForBinding(e).bindingDisconnected(e),t&&this.clearEventListenersForBinding(e)}handleError(e,t,s={}){this.application.handleError(e,`Error ${t}`,s)}clearEventListenersForBinding(e){const t=this.fetchEventListenerForBinding(e);t.hasBindings()||(t.disconnect(),this.removeMappedEventListenerFor(e))}removeMappedEventListenerFor(e){const{eventTarget:t,eventName:s,eventOptions:r}=e,n=this.fetchEventListenerMapForEventTarget(t),i=this.cacheKey(s,r);n.delete(i),0==n.size&&this.eventListenerMaps.delete(t)}fetchEventListenerForBinding(e){const{eventTarget:t,eventName:s,eventOptions:r}=e;return this.fetchEventListener(t,s,r)}fetchEventListener(e,t,s){const r=this.fetchEventListenerMapForEventTarget(e),n=this.cacheKey(t,s);let i=r.get(n);return i||(i=this.createEventListener(e,t,s),r.set(n,i)),i}createEventListener(t,s,r){const n=new e(t,s,r);return this.started&&n.connect(),n}fetchEventListenerMapForEventTarget(e){let t=this.eventListenerMaps.get(e);return t||(t=new Map,this.eventListenerMaps.set(e,t)),t}cacheKey(e,t){const s=[e];return Object.keys(t).sort().forEach((e=>{s.push(`${t[e]?"":"!"}${e}`)})),s.join(":")}}const s={stop:({event:e,value:t})=>(t&&e.stopPropagation(),!0),prevent:({event:e,value:t})=>(t&&e.preventDefault(),!0),self:({event:e,value:t,element:s})=>!t||s===e.target},r=/^(?:(?:([^.]+?)\+)?(.+?)(?:\.(.+?))?(?:@(window|document))?->)?(.+?)(?:#([^:]+?))(?::(.+))?$/;function n(e){return"window"==e?window:"document"==e?document:void 0}function i(e){return e.replace(/(?:[_-])([a-z0-9])/g,((e,t)=>t.toUpperCase()))}function o(e){return i(e.replace(/--/g,"-").replace(/__/g,"_"))}function a(e){return e.charAt(0).toUpperCase()+e.slice(1)}function c(e){return e.replace(/([A-Z])/g,((e,t)=>`-${t.toLowerCase()}`))}function l(e){return null!=e}function h(e,t){return Object.prototype.hasOwnProperty.call(e,t)}const u=["meta","ctrl","alt","shift"];class d{constructor(e,t,s,r){this.element=e,this.index=t,this.eventTarget=s.eventTarget||e,this.eventName=s.eventName||function(e){const t=e.tagName.toLowerCase();if(t in m)return m[t](e)}(e)||g("missing event name"),this.eventOptions=s.eventOptions||{},this.identifier=s.identifier||g("missing identifier"),this.methodName=s.methodName||g("missing method name"),this.keyFilter=s.keyFilter||"",this.schema=r}static forToken(e,t){return new this(e.element,e.index,function(e){const t=e.trim().match(r)||[];let s=t[2],i=t[3];return i&&!["keydown","keyup","keypress"].includes(s)&&(s+=`.${i}`,i=""),{eventTarget:n(t[4]),eventName:s,eventOptions:t[7]?(o=t[7],o.split(":").reduce(((e,t)=>Object.assign(e,{[t.replace(/^!/,"")]:!/^!/.test(t)})),{})):{},identifier:t[5],methodName:t[6],keyFilter:t[1]||i};var o}(e.content),t)}toString(){const e=this.keyFilter?`.${this.keyFilter}`:"",t=this.eventTargetName?`@${this.eventTargetName}`:"";return`${this.eventName}${e}${t}->${this.identifier}#${this.methodName}`}shouldIgnoreKeyboardEvent(e){if(!this.keyFilter)return!1;const t=this.keyFilter.split("+");if(this.keyFilterDissatisfied(e,t))return!0;const s=t.filter((e=>!u.includes(e)))[0];return!!s&&(h(this.keyMappings,s)||g(`contains unknown key filter: ${this.keyFilter}`),this.keyMappings[s].toLowerCase()!==e.key.toLowerCase())}shouldIgnoreMouseEvent(e){if(!this.keyFilter)return!1;const t=[this.keyFilter];return!!this.keyFilterDissatisfied(e,t)}get params(){const e={},t=new RegExp(`^data-${this.identifier}-(.+)-param$`,"i");for(const{name:s,value:r}of Array.from(this.element.attributes)){const n=s.match(t),o=n&&n[1];o&&(e[i(o)]=p(r))}return e}get eventTargetName(){return(e=this.eventTarget)==window?"windoLine truncated
+30
View File
@@ -0,0 +1,30 @@
/**
* Bundled by jsDelivr using Rollup v2.79.2 and Terser v5.39.0.
* Original file: /npm/@hotwired/turbo@7.3.0/dist/turbo.es2017-esm.js
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
!function(){if(void 0===window.Reflect||void 0===window.customElements||window.customElements.polyfillWrapFlushCallback)return;const e=HTMLElement,t=function(){return Reflect.construct(e,[],this.constructor)};window.HTMLElement=t,HTMLElement.prototype=e.prototype,HTMLElement.prototype.constructor=HTMLElement,Object.setPrototypeOf(HTMLElement,e)}(),function(e){function t(e,t,s){throw new e("Failed to execute 'requestSubmit' on 'HTMLFormElement': "+t+".",s)}"function"!=typeof e.requestSubmit&&(e.requestSubmit=function(e){e?(!function(e,s){e instanceof HTMLElement||t(TypeError,"parameter 1 is not of type 'HTMLElement'"),"submit"==e.type||t(TypeError,"The specified element is not a submit button"),e.form==s||t(DOMException,"The specified element is not owned by this form element","NotFoundError")}(e,this),e.click()):((e=document.createElement("input")).type="submit",e.hidden=!0,this.appendChild(e),e.click(),this.removeChild(e))})}(HTMLFormElement.prototype);const e=new WeakMap;function t(t){const s=function(e){const t=e instanceof Element?e:e instanceof Node?e.parentElement:null,s=t?t.closest("input, button"):null;return"submit"==(null==s?void 0:s.type)?s:null}(t.target);s&&s.form&&e.set(s.form,s)}var s,i,r,n,o,a;!function(){if("submitter"in Event.prototype)return;let s=window.Event.prototype;if("SubmitEvent"in window&&/Apple Computer/.test(navigator.vendor))s=window.SubmitEvent.prototype;else if("SubmitEvent"in window)return;addEventListener("click",t,!0),Object.defineProperty(s,"submitter",{get(){if("submit"==this.type&&this.target instanceof HTMLFormElement)return e.get(this.target)}})}(),function(e){e.eager="eager",e.lazy="lazy"}(s||(s={}));class l extends HTMLElement{static get observedAttributes(){return["disabled","complete","loading","src"]}constructor(){super(),this.loaded=Promise.resolve(),this.delegate=new l.delegateConstructor(this)}connectedCallback(){this.delegate.connect()}disconnectedCallback(){this.delegate.disconnect()}reload(){return this.delegate.sourceURLReloaded()}attributeChangedCallback(e){"loading"==e?this.delegate.loadingStyleChanged():"complete"==e?this.delegate.completeChanged():"src"==e?this.delegate.sourceURLChanged():this.delegate.disabledChanged()}get src(){return this.getAttribute("src")}set src(e){e?this.setAttribute("src",e):this.removeAttribute("src")}get loading(){return function(e){if("lazy"===e.toLowerCase())return s.lazy;return s.eager}(this.getAttribute("loading")||"")}set loading(e){e?this.setAttribute("loading",e):this.removeAttribute("loading")}get disabled(){return this.hasAttribute("disabled")}set disabled(e){e?this.setAttribute("disabled",""):this.removeAttribute("disabled")}get autoscroll(){return this.hasAttribute("autoscroll")}set autoscroll(e){e?this.setAttribute("autoscroll",""):this.removeAttribute("autoscroll")}get complete(){return!this.delegate.isLoading}get isActive(){return this.ownerDocument===document&&!this.isPreview}get isPreview(){var e,t;return null===(t=null===(e=this.ownerDocument)||void 0===e?void 0:e.documentElement)||void 0===t?void 0:t.hasAttribute("data-turbo-preview")}}function h(e){return new URL(e.toString(),document.baseURI)}function c(e){let t;return e.hash?e.hash.slice(1):(t=e.href.match(/#(.*)$/))?t[1]:void 0}function d(e,t){return h((null==t?void 0:t.getAttribute("formaction"))||e.getAttribute("action")||e.action)}function u(e){return(function(e){return function(e){return e.pathname.split("/").slice(1)}(e).slice(-1)[0]}(e).match(/\.[^.]*$/)||[])[0]||""}function m(e,t){const s=function(e){return t=e.origin+e.pathname,t.endsWith("/")?t:t+"/";var t}(t);return e.href===h(s).href||e.href.startsWith(s)}function p(e,t){return m(e,t)&&!!u(e).match(/^(?:|\.(?:htm|html|xhtml|php))$/)}function g(e){const t=c(e);return null!=t?e.href.slice(0,-(t.length+1)):e.href}function f(e){return g(e)}class v{constructor(e){this.response=e}get succeeded(){return this.response.ok}get failed(){return!this.succeeded}get clientError(){return this.statusCode>=400&&this.statusCode<=499}get serverError(){return this.statusCode>=500&&this.statusCode<=599}get redirected(){return this.response.redirected}get location(){return h(this.response.url)}get isHTML(){return this.contentType&&this.contentType.match(/^(?:text\/([^\s;,]+\b)?html|application\/xhtml\+xml)\b/)}get statusCode(){return this.response.status}get contentType(){return this.header("Content-Type")}get responseText(){return this.response.clone().text()}get responseHTML(){return this.isHTML?this.response.clone().text():Promise.resolve(void 0)}header(e){return this.response.headers.get(e)}}function b(e){if("false"==e.getAttribute("data-turbo-eval"))return e;{const t=document.createElement("script"),s=M("csp-nonce");return s&&(t.nonce=s),t.textContent=e.textContent,t.async=!1,function(e,t){for(const{name:s,value:i}of t.attributes)e.setAttribute(s,i)}(t,e),t}}function w(e,{target:t,cancelable:s,detail:i}={}){const r=new CustomEvent(e,{cancelable:s,bubbles:!0,composed:!0,detail:i});return t&&t.isConnected?t.disLine truncated
.turbo-progress-bar {
position: fixed;
display: block;
top: 0;
left: 0;
height: 3px;
background: #0076ff;
z-index: 2147483647;
transition:
width ${X.animationDuration}ms ease-out,
opacity ${X.animationDuration/2}ms ${X.animationDuration/2}ms ease-in;
transform: translate3d(0, 0, 0);
}
`}constructor(){this.hiding=!1,this.value=0,this.visible=!1,this.trickle=()=>{this.setValue(this.value+Math.random()/100)},this.stylesheetElement=this.createStylesheetElement(),this.progressElement=this.createProgressElement(),this.installStylesheetElement(),this.setValue(0)}show(){this.visible||(this.visible=!0,this.installProgressElement(),this.startTrickling())}hide(){this.visible&&!this.hiding&&(this.hiding=!0,this.fadeProgressElement((()=>{this.uninstallProgressElement(),this.stopTrickling(),this.visible=!1,this.hiding=!1})))}setValue(e){this.value=e,this.refresh()}installStylesheetElement(){document.head.insertBefore(this.stylesheetElement,document.head.firstChild)}installProgressElement(){this.progressElement.style.width="0",this.progressElement.style.opacity="1",document.documentElement.insertBefore(this.progressElement,document.body),this.refresh()}fadeProgressElement(e){this.progressElement.style.opacity="0",setTimeout(e,1.5*X.animationDuration)}uninstallProgressElement(){this.progressElement.parentNode&&document.documentElement.removeChild(this.progressElement)}startTrickling(){this.trickleInterval||(this.trickleInterval=window.setInterval(this.trickle,X.animationDuration))}stopTrickling(){window.clearInterval(this.trickleInterval),delete this.trickleInterval}refresh(){requestAnimationFrame((()=>{this.progressElement.style.width=10+90*this.value+"%"}))}createStylesheetElement(){const e=document.createElement("style");return e.type="text/css",e.textContent=X.defaultCSS,this.cspNonce&&(e.nonce=this.cspNonce),e}createProgressElement(){const e=document.createElement("div");return e.className="turbo-progress-bar",e}get cspNonce(){return M("csp-nonce")}}X.animationDuration=300;class Y extends N{constructor(){super(...arguments),this.detailsByOuterHTML=this.children.filter((e=>!function(e){const t=e.localName;return"noscript"==t}(e))).map((e=>function(e){e.hasAttribute("nonce")&&e.setAttribute("nonce","");return e}(e))).reduce(((e,t)=>{const{outerHTML:s}=t,i=s in e?e[s]:{type:J(t),tracked:G(t),elements:[]};return Object.assign(Object.assign({},e),{[s]:Object.assign(Object.assign({},i),{elements:[...i.elements,t]})})}),{})}get trackedElementSignature(){return Object.keys(this.detailsByOuterHTML).filter((e=>this.detailsByOuterHTML[e].tracked)).join("")}getScriptElementsNotInSnapshot(e){return this.getElementsMatchingTypeNotInSnapshot("script",e)}getStylesheetElementsNotInSnapshot(e){return this.getElementsMatchingTypeNotInSnapshot("stylesheet",e)}getElementsMatchingTypeNotInSnapshot(e,t){return Object.keys(this.detailsByOuterHTML).filter((e=>!(e in t.detailsByOuterHTML))).map((e=>this.detailsByOuterHTML[e])).filter((({type:t})=>t==e)).map((({elements:[e]})=>e))}get provisionalElements(){return Object.keys(this.detailsByOuterHTML).reduce(((e,t)=>{const{type:s,tracked:i,elements:r}=this.detailsByOuterHTML[t];return null!=s||i?r.length>1?[...e,...r.slice(1)]:e:[...e,...r]}),[])}getMetaValue(e){const t=this.findMetaElementByName(e);return t?t.getAttribute("content"):null}findMetaElementByName(e){return Object.keys(this.detailsByOuterHTML).reduce(((t,s)=>{const{elements:[i]}=this.detailsByOuterHTML[s];return function(e,t){const s=e.localName;return"meta"==s&&e.getAttribute("name")==t}(i,e)?i:t}),void 0)}}function J(e){return function(e){const t=e.localName;return"script"==t}(e)?"script":function(e){const t=e.localName;return"style"==t||"link"==t&&"stylesheet"==e.getAttribute("rel")}(e)?"stylesheet":void 0}function G(e){return"reload"==e.getAttribute("data-turbo-track")}class Z extends N{static fromHTMLString(e=""){return this.fromDocument(E(e))}static fromElement(e){return this.fromDocument(e.ownerDocument)}static fromDocument({head:e,body:t}){return new this(t,new Y(e))}constructor(e,t){super(e),this.headSnapshot=t}clone(){const e=this.element.cloneNode(!0),t=this.element.querySelectorAll("select"),s=e.querySelectorAll("select");for(const[e,i]of t.entries()){const t=s[e];for(const e of t.selectedOptions)e.selected=!1;for(const e of i.selectedOptions)t.options[e.index].selected=!0}for(const t of e.querySelectorAll('input[type="password"]'))t.value="";return new Z(e,this.headSnapshot)}get headElement(){return this.headSnapshot.element}get rootLocation(){var e;return h(null!==(e=this.getSetting("root"))&&void 0!==e?e:"/")}get cacheControlValue(){return this.getSetting("cache-control")}get isPreviewable(){return"no-preview"!=this.cacheControlValue}get isCacheable(){return"no-cache"!=this.cacheControlValue}get isVisitable(){return"reload"!=this.getSetting("visit-control")}getSetting(e){return this.headSnapshot.getMetaValue(`turbo-${e}`)}}!function(e){e.visitStart="visitStart",e.requestStart="requestStart",e.requestEnd="requestEnd",e.visitEnd="visitEnd"}(o||(o={})),function(e){e.initialized="initialized",e.started="started",e.canceled="canceled",e.failed="failed",e.completed="completed"}(a||(a={}));const ee={action:"advance",historyChanged:!1,visitCachedSnapshot:()=>{},willRender:!0,updateHistory:!0,shouldCach Line truncated
You are loading Turbo from a <script> element inside the <body> element. This is probably not what you meant to do!
Load your application’s JavaScript bundle inside the <head> element instead. <script> elements in <body> are evaluated with each page change.
For more information, see: https://turbo.hotwired.dev/handbook/building#working-with-script-elements
——
Suppress this warning by adding a "data-turbo-suppress-warning" attribute to: %s
`,e.outerHTML);e=e.parentElement}})(),window.Turbo=Be,Ce();export{l as FrameElement,s as FrameLoadingStyle,Q as FrameRenderer,ge as PageRenderer,Z as PageSnapshot,Ee as StreamActions,We as StreamElement,De as StreamSourceElement,Le as cache,Me as clearCache,Pe as connectStreamSource,Fe as disconnectStreamSource,Re as navigator,Te as registerAdapter,ke as renderStreamMessage,ye as session,He as setConfirmMethod,qe as setFormMode,Ie as setProgressBarDelay,Ce as start,Ae as visit};export default null;
+22
View File
@@ -0,0 +1,22 @@
<?php return array (
'@hotwired/stimulus' =>
array (
'version' => '3.2.2',
'dependencies' =>
array (
),
'extraFiles' =>
array (
),
),
'@hotwired/turbo' =>
array (
'version' => '7.3.0',
'dependencies' =>
array (
),
'extraFiles' =>
array (
),
),
);
Executable
+21
View File
@@ -0,0 +1,21 @@
#!/usr/bin/env php
<?php
use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
if (!is_dir(dirname(__DIR__).'/vendor')) {
throw new LogicException('Dependencies are missing. Try running "composer install".');
}
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);
};
Executable
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env php
<?php
require dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit';
+18
View File
@@ -0,0 +1,18 @@
services:
###> doctrine/doctrine-bundle ###
database:
ports:
- "5432"
###< doctrine/doctrine-bundle ###
###> symfony/mailer ###
mailer:
image: axllent/mailpit
ports:
- "1025"
- "8025"
environment:
MP_SMTP_AUTH_ACCEPT_ANY: 1
MP_SMTP_AUTH_ALLOW_INSECURE: 1
###< symfony/mailer ###
+30
View File
@@ -0,0 +1,30 @@
services:
database:
image: postgres:${POSTGRES_VERSION:-16}-alpine
ports:
- "5432"
environment:
POSTGRES_DB: ${POSTGRES_DB:-app}
# You should definitely change the password in production
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!}
POSTGRES_USER: ${POSTGRES_USER:-app}
healthcheck:
test: ["CMD", "pg_isready", "-d", "${POSTGRES_DB:-app}", "-U", "${POSTGRES_USER:-app}"]
timeout: 5s
retries: 5
start_period: 60s
volumes:
- database_data:/var/lib/postgresql/data:rw
mailer:
image: axllent/mailpit
ports:
- "1025"
- "8025"
environment:
MP_SMTP_AUTH_ACCEPT_ANY: 1
MP_SMTP_AUTH_ALLOW_INSECURE: 1
volumes:
database_data:
+109
View File
@@ -0,0 +1,109 @@
{
"type": "project",
"license": "proprietary",
"minimum-stability": "stable",
"prefer-stable": true,
"require": {
"php": ">=8.4",
"ext-ctype": "*",
"ext-iconv": "*",
"doctrine/doctrine-bundle": "^3.2",
"doctrine/doctrine-migrations-bundle": "^4.0",
"doctrine/orm": "^3.6",
"phpdocumentor/reflection-docblock": "^5.6",
"phpstan/phpdoc-parser": "^2.3",
"symfony/asset": "8.0.*",
"symfony/asset-mapper": "8.0.*",
"symfony/console": "8.0.*",
"symfony/doctrine-messenger": "8.0.*",
"symfony/dotenv": "8.0.*",
"symfony/expression-language": "8.0.*",
"symfony/flex": "^2",
"symfony/form": "8.0.*",
"symfony/framework-bundle": "8.0.*",
"symfony/http-client": "8.0.*",
"symfony/intl": "8.0.*",
"symfony/mailer": "8.0.*",
"symfony/mime": "8.0.*",
"symfony/monolog-bundle": "^4.0",
"symfony/notifier": "8.0.*",
"symfony/process": "8.0.*",
"symfony/property-access": "8.0.*",
"symfony/property-info": "8.0.*",
"symfony/runtime": "8.0.*",
"symfony/security-bundle": "8.0.*",
"symfony/serializer": "8.0.*",
"symfony/stimulus-bundle": "^2.32",
"symfony/string": "8.0.*",
"symfony/translation": "8.0.*",
"symfony/twig-bundle": "8.0.*",
"symfony/ux-turbo": "^2.32",
"symfony/validator": "8.0.*",
"symfony/web-link": "8.0.*",
"symfony/yaml": "8.0.*",
"twig/extra-bundle": "^2.12|^3.0",
"twig/twig": "^2.12|^3.0"
},
"config": {
"allow-plugins": {
"php-http/discovery": true,
"symfony/flex": true,
"symfony/runtime": true
},
"bump-after-update": true,
"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": "*",
"symfony/polyfill-php73": "*",
"symfony/polyfill-php74": "*",
"symfony/polyfill-php80": "*",
"symfony/polyfill-php81": "*",
"symfony/polyfill-php82": "*",
"symfony/polyfill-php83": "*",
"symfony/polyfill-php84": "*"
},
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd",
"importmap:install": "symfony-cmd"
},
"post-install-cmd": [
"@auto-scripts"
],
"post-update-cmd": [
"@auto-scripts"
]
},
"conflict": {
"symfony/symfony": "*"
},
"extra": {
"symfony": {
"allow-contrib": false,
"require": "8.0.*"
}
},
"require-dev": {
"phpunit/phpunit": "^13.0",
"symfony/browser-kit": "8.0.*",
"symfony/css-selector": "8.0.*",
"symfony/debug-bundle": "8.0.*",
"symfony/maker-bundle": "^1.0",
"symfony/stopwatch": "8.0.*",
"symfony/web-profiler-bundle": "8.0.*"
}
}
Generated
+9828
View File
File diff suppressed because it is too large. Load diff
+16
View 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\UX\StimulusBundle\StimulusBundle::class => ['all' => true],
Symfony\UX\Turbo\TurboBundle::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],
];
+11
View File
@@ -0,0 +1,11 @@
framework:
asset_mapper:
# The paths to make available to the asset mapper.
paths:
- assets/
missing_import_mode: strict
when@prod:
framework:
asset_mapper:
missing_import_mode: warn
+19
View 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
+11
View File
@@ -0,0 +1,11 @@
# Enable stateless CSRF protection for forms and logins/logouts
framework:
form:
csrf_protection:
token_id: submit
csrf_protection:
stateless_token_ids:
- submit
- authenticate
- logout
+5
View 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)%"
+44
View File
@@ -0,0 +1,44 @@
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
server_version: '16'
profiling_collect_backtrace: '%kernel.debug%'
orm:
validate_xml_mapping: true
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
identity_generation_preferences:
Doctrine\DBAL\Platforms\PostgreSQLPlatform: identity
auto_mapping: true
mappings:
App:
type: attribute
is_bundle: false
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
controller_resolver:
auto_mapping: false
when@test:
doctrine:
dbal:
# "TEST_TOKEN" is typically set by ParaTest
dbname_suffix: '_test%env(default::TEST_TOKEN)%'
when@prod:
doctrine:
orm:
query_cache_driver:
type: pool
pool: doctrine.system_cache_pool
result_cache_driver:
type: pool
pool: doctrine.result_cache_pool
framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app
doctrine.system_cache_pool:
adapter: cache.system
+6
View File
@@ -0,0 +1,6 @@
doctrine_migrations:
migrations_paths:
# namespace is arbitrary but should be different from App\Migrations
# as migrations classes should NOT be autoloaded
'DoctrineMigrations': '%kernel.project_dir%/migrations'
enable_profiler: false
+15
View File
@@ -0,0 +1,15 @@
# see https://symfony.com/doc/current/reference/configuration/framework.html
framework:
secret: '%env(APP_SECRET)%'
# Note that the session will be started ONLY if you read or write from it.
session: true
#esi: true
#fragments: true
when@test:
framework:
test: true
session:
storage_factory_id: session.storage.factory.mock_file
+3
View File
@@ -0,0 +1,3 @@
framework:
mailer:
dsn: '%env(MAILER_DSN)%'
+26
View File
@@ -0,0 +1,26 @@
framework:
messenger:
failure_transport: failed
transports:
# https://symfony.com/doc/current/messenger.html#transport-configuration
async:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
retry_strategy:
max_retries: 3
multiplier: 2
failed: 'doctrine://default?queue_name=failed'
# sync: 'sync://'
default_bus: messenger.bus.default
buses:
messenger.bus.default: []
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
+55
View File
@@ -0,0 +1,55 @@
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"]
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]
channels: ["!deprecation"]
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
formatter: monolog.formatter.json
+12
View File
@@ -0,0 +1,12 @@
framework:
notifier:
chatter_transports:
texter_transports:
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 }
+3
View File
@@ -0,0 +1,3 @@
framework:
property_info:
with_constructor_extractor: true
+10
View File
@@ -0,0 +1,10 @@
framework:
router:
# 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: '%env(DEFAULT_URI)%'
when@prod:
framework:
router:
strict_requirements: null
+39
View File
@@ -0,0 +1,39 @@
security:
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
providers:
users_in_memory: { memory: null }
firewalls:
dev:
# Ensure dev tools and static assets are always allowed
pattern: ^/(_profiler|_wdt|assets|build)/
security: false
main:
lazy: true
provider: users_in_memory
# 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
# Note: Only the *first* matching rule is applied
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
when@test:
security:
password_hashers:
# Password hashers are resource-intensive by design to ensure security.
# In tests, it's safe to reduce their cost to improve performance.
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
+5
View File
@@ -0,0 +1,5 @@
framework:
default_locale: en
translator:
default_path: '%kernel.project_dir%/translations'
providers:
+6
View File
@@ -0,0 +1,6 @@
twig:
file_name_pattern: '*.twig'
when@test:
twig:
strict_variables: true
+4
View File
@@ -0,0 +1,4 @@
# Enable stateless CSRF protection for forms and logins/logouts
framework:
csrf_protection:
check_header: true
+11
View File
@@ -0,0 +1,11 @@
framework:
validation:
# Enables validator auto-mapping support.
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
#auto_mapping:
# App\Entity\: []
when@test:
framework:
validation:
not_compromised_password: false
+13
View File
@@ -0,0 +1,13 @@
when@dev:
web_profiler:
toolbar: true
framework:
profiler:
collect_serializer_data: true
when@test:
framework:
profiler:
collect: false
collect_serializer_data: true
+5
View 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';
}
+1613
View File
File diff suppressed because it is too large. Load diff
+11
View File
@@ -0,0 +1,11 @@
# yaml-language-server: $schema=../vendor/symfony/routing/Loader/schema/routing.schema.json
# This file is the entry point to configure the routes of your app.
# Methods with the #[Route] attribute are automatically imported.
# See also https://symfony.com/doc/current/routing.html
# To list all registered routes, run the following command:
# bin/console debug:router
controllers:
resource: routing.controllers
+4
View File
@@ -0,0 +1,4 @@
when@dev:
_errors:
resource: '@FrameworkBundle/Resources/config/routing/errors.php'
prefix: /_error
+3
View File
@@ -0,0 +1,3 @@
_security_logout:
resource: security.route_loader.logout
type: service
+8
View File
@@ -0,0 +1,8 @@
when@dev:
web_profiler_wdt:
resource: '@WebProfilerBundle/Resources/config/routing/wdt.php'
prefix: /_wdt
web_profiler_profiler:
resource: '@WebProfilerBundle/Resources/config/routing/profiler.php'
prefix: /_profiler
+21
View File
@@ -0,0 +1,21 @@
# yaml-language-server: $schema=../vendor/symfony/dependency-injection/Loader/schema/services.schema.json
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# See also https://symfony.com/doc/current/service_container/import.html
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
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/'
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
+28
View File
@@ -0,0 +1,28 @@
<?php
/**
* Returns the importmap for this application.
*
* - "path" is a path inside the asset mapper system. Use the
* "debug:asset-map" command to see the full list of paths.
*
* - "entrypoint" (JavaScript only) set to true for any module that will
* be used as an "entrypoint" (and passed to the importmap() Twig function).
*
* The "importmap:require" command can be used to add new entries to this file.
*/
return [
'app' => [
'path' => './assets/app.js',
'entrypoint' => true,
],
'@hotwired/stimulus' => [
'version' => '3.2.2',
],
'@symfony/stimulus-bundle' => [
'path' => './vendor/symfony/stimulus-bundle/assets/dist/loader.js',
],
'@hotwired/turbo' => [
'version' => '7.3.0',
],
];
+44
View File
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
failOnDeprecation="true"
failOnNotice="true"
failOnWarning="true"
bootstrap="tests/bootstrap.php"
cacheDirectory=".phpunit.cache"
>
<php>
<ini name="display_errors" value="1" />
<ini name="error_reporting" value="-1" />
<server name="APP_ENV" value="test" force="true" />
<server name="SHELL_VERBOSITY" value="-1" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<source ignoreSuppressionOfDeprecations="true"
ignoreIndirectDeprecations="true"
restrictNotices="true"
restrictWarnings="true"
>
<include>
<directory>src</directory>
</include>
<deprecationTrigger>
<method>Doctrine\Deprecations\Deprecation::trigger</method>
<method>Doctrine\Deprecations\Deprecation::delegateTriggerToBackend</method>
<function>trigger_deprecation</function>
</deprecationTrigger>
</source>
<extensions>
</extensions>
</phpunit>
+9
View 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']);
};
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class HomeController extends AbstractController
{
#[Route('/hello')]
public function hello(): Response
{
return $this->render('hello.html.twig', [
'name' => 'Melvin'
]);
}
}
+11
View File
@@ -0,0 +1,11 @@
<?php
namespace App;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
}
+325
View File
@@ -0,0 +1,325 @@
{
"doctrine/deprecations": {
"version": "1.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "87424683adc81d7dc305eefec1fced883084aab9"
}
},
"doctrine/doctrine-bundle": {
"version": "3.2",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.0",
"ref": "18ee08e513ba0303fd09a01fc1c934870af06ffa"
},
"files": [
"config/packages/doctrine.yaml",
"src/Entity/.gitignore",
"src/Repository/.gitignore"
]
},
"doctrine/doctrine-migrations-bundle": {
"version": "4.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.1",
"ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33"
},
"files": [
"config/packages/doctrine_migrations.yaml",
"migrations/.gitignore"
]
},
"phpunit/phpunit": {
"version": "13.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "11.1",
"ref": "1117deb12541f35793eec9fff7494d7aa12283fc"
},
"files": [
".env.test",
"phpunit.dist.xml",
"tests/bootstrap.php",
"bin/phpunit"
]
},
"symfony/asset-mapper": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.4",
"ref": "5ad1308aa756d58f999ffbe1540d1189f5d7d14a"
},
"files": [
"assets/app.js",
"assets/styles/app.css",
"config/packages/asset_mapper.yaml",
"importmap.php"
]
},
"symfony/console": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "1781ff40d8a17d87cf53f8d4cf0c8346ed2bb461"
},
"files": [
"bin/console"
]
},
"symfony/debug-bundle": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "5aa8aa48234c8eb6dbdd7b3cd5d791485d2cec4b"
},
"files": [
"config/packages/debug.yaml"
]
},
"symfony/flex": {
"version": "2.10",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.4",
"ref": "52e9754527a15e2b79d9a610f98185a1fe46622a"
},
"files": [
".env",
".env.dev"
]
},
"symfony/form": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.2",
"ref": "7d86a6723f4a623f59e2bf966b6aad2fc461d36b"
},
"files": [
"config/packages/csrf.yaml"
]
},
"symfony/framework-bundle": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.4",
"ref": "09f6e081c763a206802674ce0cb34a022f0ffc6d"
},
"files": [
"config/packages/cache.yaml",
"config/packages/framework.yaml",
"config/preload.php",
"config/routes/framework.yaml",
"config/services.yaml",
"public/index.php",
"src/Controller/.gitignore",
"src/Kernel.php",
".editorconfig"
]
},
"symfony/mailer": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "4.3",
"ref": "09051cfde49476e3c12cd3a0e44289ace1c75a4f"
},
"files": [
"config/packages/mailer.yaml"
]
},
"symfony/maker-bundle": {
"version": "1.66",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
}
},
"symfony/messenger": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.0",
"ref": "d8936e2e2230637ef97e5eecc0eea074eecae58b"
},
"files": [
"config/packages/messenger.yaml"
]
},
"symfony/monolog-bundle": {
"version": "4.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.7",
"ref": "1b9efb10c54cb51c713a9391c9300ff8bceda459"
},
"files": [
"config/packages/monolog.yaml"
]
},
"symfony/notifier": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.0",
"ref": "178877daf79d2dbd62129dd03612cb1a2cb407cc"
},
"files": [
"config/packages/notifier.yaml"
]
},
"symfony/property-info": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.3",
"ref": "dae70df71978ae9226ae915ffd5fad817f5ca1f7"
},
"files": [
"config/packages/property_info.yaml"
]
},
"symfony/routing": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.4",
"ref": "bc94c4fd86f393f3ab3947c18b830ea343e51ded"
},
"files": [
"config/packages/routing.yaml",
"config/routes.yaml"
]
},
"symfony/security-bundle": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.4",
"ref": "c42fee7802181cdd50f61b8622715829f5d2335c"
},
"files": [
"config/packages/security.yaml",
"config/routes/security.yaml"
]
},
"symfony/stimulus-bundle": {
"version": "2.32",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.24",
"ref": "3357f2fa6627b93658d8e13baa416b2a94a50c5f"
},
"files": [
"assets/controllers.json",
"assets/controllers/csrf_protection_controller.js",
"assets/controllers/hello_controller.js",
"assets/stimulus_bootstrap.js"
]
},
"symfony/translation": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.3",
"ref": "620a1b84865ceb2ba304c8f8bf2a185fbf32a843"
},
"files": [
"config/packages/translation.yaml",
"translations/.gitignore"
]
},
"symfony/twig-bundle": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.4",
"ref": "cab5fd2a13a45c266d45a7d9337e28dee6272877"
},
"files": [
"config/packages/twig.yaml",
"templates/base.html.twig"
]
},
"symfony/ux-turbo": {
"version": "2.32",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.20",
"ref": "287f7c6eb6e9b65e422d34c00795b360a787380b"
},
"files": [
"config/packages/ux_turbo.yaml"
]
},
"symfony/validator": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.0",
"ref": "8c1c4e28d26a124b0bb273f537ca8ce443472bfd"
},
"files": [
"config/packages/validator.yaml"
]
},
"symfony/web-profiler-bundle": {
"version": "8.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.3",
"ref": "a363460c1b0b4a4d0242f2ce1a843ca0f6ac9026"
},
"files": [
"config/packages/web_profiler.yaml",
"config/routes/web_profiler.yaml"
]
},
"symfony/webapp-pack": {
"version": "1.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "b9e6cc8e7b6069d0e8a816665809a423864eb4dd"
},
"files": [
"config/packages/messenger.yaml"
]
},
"twig/extra-bundle": {
"version": "v3.23.0"
}
}
+17
View File
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text><text y=%221.3em%22 x=%220.2em%22 font-size=%2276%22 fill=%22%23fff%22>sf</text></svg>">
{% block stylesheets %}
{% endblock %}
{% block javascripts %}
{% block importmap %}{{ importmap('app') }}{% endblock %}
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
+2
View File
@@ -0,0 +1,2 @@
{# templates/hellp.html.twig #}
<h1>Hello ! {{ name }}</h1>
+13
View File
@@ -0,0 +1,13 @@
<?php
use Symfony\Component\Dotenv\Dotenv;
require dirname(__DIR__).'/vendor/autoload.php';
if (method_exists(Dotenv::class, 'bootEnv')) {
(new Dotenv())->bootEnv(dirname(__DIR__).'/.env');
}
if ($_SERVER['APP_DEBUG']) {
umask(0000);
}