docs: README, OrbStack notes, autoload fallback for deploys without composer
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -1 +1 @@
|
|||||||
{"version":2,"defects":{"Weerscherm\\Tests\\DashboardServiceTest::testForecastUsesStationLocationUnlessConfigured":7,"Weerscherm\\Tests\\DashboardServiceTest::testMeasureFailureFallsBackToSumRain24":7,"Weerscherm\\Tests\\NetatmoClientTest::testRejectedTokenAlreadyReplacedByOtherProcessIsReusedWithoutRefresh":8},"times":{"Weerscherm\\Tests\\ConfigTest::testDefaultsApplyWhenKeysAreMissing":0,"Weerscherm\\Tests\\ConfigTest::testFileValuesOverrideDefaults":0,"Weerscherm\\Tests\\ConfigTest::testUnknownKeyReturnsGivenDefault":0,"Weerscherm\\Tests\\ConfigTest::testFileMustReturnArray":0,"Weerscherm\\Tests\\StationMapperTest::testStationMetadata":0,"Weerscherm\\Tests\\StationMapperTest::testOutdoor":0,"Weerscherm\\Tests\\StationMapperTest::testIndoorDefaultOrderAndUnreachableModule":0,"Weerscherm\\Tests\\StationMapperTest::testIndoorConfigDeterminesOrderAndLabels":0,"Weerscherm\\Tests\\StationMapperTest::testRainModule":0,"Weerscherm\\Tests\\StationMapperTest::testWithoutRainModule":0,"Weerscherm\\Tests\\StationMapperTest::testUnreachableOutdoorModuleGivesNulls":0,"Weerscherm\\Tests\\StationMapperTest::testUnknownDeviceIdFallsBackToFirstStation":0,"Weerscherm\\Tests\\StationMapperTest::testEmptyDevicesGivesNullsWithoutCrashing":0,"Weerscherm\\Tests\\RainCalculatorTest::testNormalWeek":0,"Weerscherm\\Tests\\RainCalculatorTest::testMissingPreviousDayIsNullAndExcludedFromTotal":0,"Weerscherm\\Tests\\RainCalculatorTest::testMissingTodayFallsBackToSumRain24":0,"Weerscherm\\Tests\\RainCalculatorTest::testMonthBoundaryKeepsPreviousDaysButNotInMonthTotal":0,"Weerscherm\\Tests\\RainCalculatorTest::testDaylightSavingTransitionMapsTimestampsToLocalDates":0,"Weerscherm\\Tests\\RainCalculatorTest::testEmptyBodyGivesNulls":0,"Weerscherm\\Tests\\RainCalculatorTest::testDateBeginIsMinOfFirstOfMonthAndThreeDaysAgo":0,"Weerscherm\\Tests\\CacheTest::testWriteThenReadRoundTrip":0.003,"Weerscherm\\Tests\\CacheTest::testMissingKeyReadsNull":0.004,"Weerscherm\\Tests\\CacheTest::testCorruptFileReadsNull":0,"Weerscherm\\Tests\\CacheTest::testFreshness":0.001,"Weerscherm\\Tests\\CacheTest::testKeyIsSanitised":0,"Weerscherm\\Tests\\CacheTest::testWriteCreatesDirectory":0,"Weerscherm\\Tests\\ForecastMapperTest::testSkipsTodayAndReturnsFiveDays":0,"Weerscherm\\Tests\\ForecastMapperTest::testNullValuesStayNull":0,"Weerscherm\\Tests\\ForecastMapperTest::testShorterResponseGivesFewerDays":0,"Weerscherm\\Tests\\ForecastMapperTest::testMissingTimeArrayGivesEmptyList":0,"Weerscherm\\Tests\\DashboardServiceTest::testHappyPathMatchesContract":0.001,"Weerscherm\\Tests\\DashboardServiceTest::testMeasureIsRequestedForRainModuleFromMidnightOfDateBegin":0.001,"Weerscherm\\Tests\\DashboardServiceTest::testForecastUsesStationLocationUnlessConfigured":0.001,"Weerscherm\\Tests\\DashboardServiceTest::testStationsFailureWithoutCacheGivesNullsAndError":0,"Weerscherm\\Tests\\DashboardServiceTest::testStationsFailureWithCacheServesStaleData":0.001,"Weerscherm\\Tests\\DashboardServiceTest::testAuthFailureGivesNetatmoAuthError":0.001,"Weerscherm\\Tests\\DashboardServiceTest::testMeasureFailureFallsBackToSumRain24":0.001,"Weerscherm\\Tests\\DashboardServiceTest::testForecastFailureLeavesRestIntact":0.001,"Weerscherm\\Tests\\DashboardServiceTest::testSecondBuildWithinTtlUsesCache":0.001,"Weerscherm\\Tests\\TokenStoreTest::testWriteReadRoundTripAndMode":0,"Weerscherm\\Tests\\TokenStoreTest::testMissingOrInvalidFileReadsNull":0,"Weerscherm\\Tests\\TokenStoreTest::testWithLockReturnsValueAndReleasesAfterException":0,"Weerscherm\\Tests\\TokenStoreTest::testConcurrentProcessesAreSerialised":0.443,"Weerscherm\\Tests\\NetatmoClientTest::testValidTokenIsUsedWithoutRefresh":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testExpiringTokenIsRefreshedAndRotatedRefreshTokenStored":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testFreshlyInitialisedStoreWithoutAccessTokenRefreshesFirst":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testUnauthorizedResponseTriggersOneRefreshAndRetry":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testSecondUnauthorizedResponseIsAuthError":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testInvalidGrantIsAuthError":0,"Weerscherm\\Tests\\NetatmoClientTest::testMissingTokenFileIsAuthError":0,"Weerscherm\\Tests\\NetatmoClientTest::testServerErrorIsUpstreamError":0,"Weerscherm\\Tests\\NetatmoClientTest::testRefreshServerErrorIsUpstreamNotAuth":0,"Weerscherm\\Tests\\NetatmoClientTest::testConcurrentClientsShareOneRefresh":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testRejectedTokenAlreadyReplacedByOtherProcessIsReusedWithoutRefresh":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testGetMeasureQuery":0,"Weerscherm\\Tests\\OpenMeteoClientTest::testRequestsSixDaysWithAllDailyVariables":0,"Weerscherm\\Tests\\OpenMeteoClientTest::testErrorStatusIsUpstreamException":0,"Weerscherm\\Tests\\OpenMeteoClientTest::testMissingDailyIsUpstreamException":0}}
|
{"version":2,"defects":{"Weerscherm\\Tests\\DashboardServiceTest::testForecastUsesStationLocationUnlessConfigured":7,"Weerscherm\\Tests\\DashboardServiceTest::testMeasureFailureFallsBackToSumRain24":7,"Weerscherm\\Tests\\NetatmoClientTest::testRejectedTokenAlreadyReplacedByOtherProcessIsReusedWithoutRefresh":8},"times":{"Weerscherm\\Tests\\ConfigTest::testDefaultsApplyWhenKeysAreMissing":0,"Weerscherm\\Tests\\ConfigTest::testFileValuesOverrideDefaults":0,"Weerscherm\\Tests\\ConfigTest::testUnknownKeyReturnsGivenDefault":0,"Weerscherm\\Tests\\ConfigTest::testFileMustReturnArray":0,"Weerscherm\\Tests\\StationMapperTest::testStationMetadata":0,"Weerscherm\\Tests\\StationMapperTest::testOutdoor":0,"Weerscherm\\Tests\\StationMapperTest::testIndoorDefaultOrderAndUnreachableModule":0,"Weerscherm\\Tests\\StationMapperTest::testIndoorConfigDeterminesOrderAndLabels":0,"Weerscherm\\Tests\\StationMapperTest::testRainModule":0,"Weerscherm\\Tests\\StationMapperTest::testWithoutRainModule":0,"Weerscherm\\Tests\\StationMapperTest::testUnreachableOutdoorModuleGivesNulls":0,"Weerscherm\\Tests\\StationMapperTest::testUnknownDeviceIdFallsBackToFirstStation":0,"Weerscherm\\Tests\\StationMapperTest::testEmptyDevicesGivesNullsWithoutCrashing":0,"Weerscherm\\Tests\\RainCalculatorTest::testNormalWeek":0,"Weerscherm\\Tests\\RainCalculatorTest::testMissingPreviousDayIsNullAndExcludedFromTotal":0,"Weerscherm\\Tests\\RainCalculatorTest::testMissingTodayFallsBackToSumRain24":0,"Weerscherm\\Tests\\RainCalculatorTest::testMonthBoundaryKeepsPreviousDaysButNotInMonthTotal":0,"Weerscherm\\Tests\\RainCalculatorTest::testDaylightSavingTransitionMapsTimestampsToLocalDates":0,"Weerscherm\\Tests\\RainCalculatorTest::testEmptyBodyGivesNulls":0,"Weerscherm\\Tests\\RainCalculatorTest::testDateBeginIsMinOfFirstOfMonthAndThreeDaysAgo":0,"Weerscherm\\Tests\\CacheTest::testWriteThenReadRoundTrip":0.003,"Weerscherm\\Tests\\CacheTest::testMissingKeyReadsNull":0.004,"Weerscherm\\Tests\\CacheTest::testCorruptFileReadsNull":0,"Weerscherm\\Tests\\CacheTest::testFreshness":0.001,"Weerscherm\\Tests\\CacheTest::testKeyIsSanitised":0,"Weerscherm\\Tests\\CacheTest::testWriteCreatesDirectory":0,"Weerscherm\\Tests\\ForecastMapperTest::testSkipsTodayAndReturnsFiveDays":0,"Weerscherm\\Tests\\ForecastMapperTest::testNullValuesStayNull":0,"Weerscherm\\Tests\\ForecastMapperTest::testShorterResponseGivesFewerDays":0,"Weerscherm\\Tests\\ForecastMapperTest::testMissingTimeArrayGivesEmptyList":0,"Weerscherm\\Tests\\DashboardServiceTest::testHappyPathMatchesContract":0.002,"Weerscherm\\Tests\\DashboardServiceTest::testMeasureIsRequestedForRainModuleFromMidnightOfDateBegin":0.001,"Weerscherm\\Tests\\DashboardServiceTest::testForecastUsesStationLocationUnlessConfigured":0.001,"Weerscherm\\Tests\\DashboardServiceTest::testStationsFailureWithoutCacheGivesNullsAndError":0,"Weerscherm\\Tests\\DashboardServiceTest::testStationsFailureWithCacheServesStaleData":0.001,"Weerscherm\\Tests\\DashboardServiceTest::testAuthFailureGivesNetatmoAuthError":0.001,"Weerscherm\\Tests\\DashboardServiceTest::testMeasureFailureFallsBackToSumRain24":0,"Weerscherm\\Tests\\DashboardServiceTest::testForecastFailureLeavesRestIntact":0.001,"Weerscherm\\Tests\\DashboardServiceTest::testSecondBuildWithinTtlUsesCache":0.001,"Weerscherm\\Tests\\TokenStoreTest::testWriteReadRoundTripAndMode":0,"Weerscherm\\Tests\\TokenStoreTest::testMissingOrInvalidFileReadsNull":0,"Weerscherm\\Tests\\TokenStoreTest::testWithLockReturnsValueAndReleasesAfterException":0,"Weerscherm\\Tests\\TokenStoreTest::testConcurrentProcessesAreSerialised":0.438,"Weerscherm\\Tests\\NetatmoClientTest::testValidTokenIsUsedWithoutRefresh":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testExpiringTokenIsRefreshedAndRotatedRefreshTokenStored":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testFreshlyInitialisedStoreWithoutAccessTokenRefreshesFirst":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testUnauthorizedResponseTriggersOneRefreshAndRetry":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testSecondUnauthorizedResponseIsAuthError":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testInvalidGrantIsAuthError":0,"Weerscherm\\Tests\\NetatmoClientTest::testMissingTokenFileIsAuthError":0,"Weerscherm\\Tests\\NetatmoClientTest::testServerErrorIsUpstreamError":0,"Weerscherm\\Tests\\NetatmoClientTest::testRefreshServerErrorIsUpstreamNotAuth":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testConcurrentClientsShareOneRefresh":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testRejectedTokenAlreadyReplacedByOtherProcessIsReusedWithoutRefresh":0.001,"Weerscherm\\Tests\\NetatmoClientTest::testGetMeasureQuery":0,"Weerscherm\\Tests\\OpenMeteoClientTest::testRequestsSixDaysWithAllDailyVariables":0,"Weerscherm\\Tests\\OpenMeteoClientTest::testErrorStatusIsUpstreamException":0,"Weerscherm\\Tests\\OpenMeteoClientTest::testMissingDailyIsUpstreamException":0}}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
# Weerscherm
|
||||||
|
|
||||||
|
Een PWA voor een iPad mini (liggend) in de woonkamer. Toont de actuele gegevens van een
|
||||||
|
Netatmo-weerstation (buiten, drie binnenruimtes, regen) en een verwachting voor vijf dagen van Open-Meteo.
|
||||||
|
|
||||||
|
- Spec: [docs/weerscherm-spec.md](docs/weerscherm-spec.md)
|
||||||
|
- Mockup (ontwerp A is leidend): [docs/design/weerscherm-layouts.html](docs/design/weerscherm-layouts.html)
|
||||||
|
- Implementatieplan: [docs/superpowers/plans/2026-09-11-weerscherm.md](docs/superpowers/plans/2026-09-11-weerscherm.md)
|
||||||
|
|
||||||
|
```
|
||||||
|
iPad (PWA) ──GET /api/data.php──▶ PHP-backend ──▶ Netatmo API
|
||||||
|
│ └──▶ Open-Meteo API
|
||||||
|
└── storage/ (tokens + cache)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Vereisten
|
||||||
|
|
||||||
|
- PHP 8.3 met `ext-curl` en `ext-json`. Geen framework, geen runtime-dependencies.
|
||||||
|
- Composer alleen voor PHPUnit (dev). Node 20+ alleen voor de JS-tests (dev).
|
||||||
|
- Een webserver met `public/` als document root. `storage/` ligt daarbuiten en moet schrijfbaar zijn voor de webserver.
|
||||||
|
|
||||||
|
## Installatie
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone <repo> weerscherm
|
||||||
|
cd weerscherm
|
||||||
|
composer install # alleen nodig voor tests; de app draait ook zonder vendor/
|
||||||
|
cp config.example.php config.php
|
||||||
|
mkdir -p storage && chmod 750 storage
|
||||||
|
```
|
||||||
|
|
||||||
|
Vul `config.php` in. De sleutels:
|
||||||
|
|
||||||
|
| Sleutel | Betekenis |
|
||||||
|
|---|---|
|
||||||
|
| `data_source` | `fixture` (voorbeelddata, geen koppeling nodig) of `live` |
|
||||||
|
| `netatmo_client_id`, `netatmo_client_secret` | uit de app op dev.netatmo.com |
|
||||||
|
| `netatmo_device_id` | optioneel, `_id` van het basisstation; leeg = eerste station |
|
||||||
|
| `timezone` | fallback als het station geen tijdzone meldt (standaard `Europe/Berlin`) |
|
||||||
|
| `forecast_lat`, `forecast_lon` | optioneel; leeg = locatie van het station |
|
||||||
|
| `indoor_modules` | optioneel, `_id => label` in de gewenste volgorde; leeg = Netatmo-namen |
|
||||||
|
| `cache_ttl` | seconden per bron: `stations` 300, `measure` 900, `forecast` 3600 |
|
||||||
|
| `storage_path` | map voor tokens en cache, buiten de docroot |
|
||||||
|
|
||||||
|
`config.php` en `storage/` staan in `.gitignore` en komen nooit in git.
|
||||||
|
|
||||||
|
## Netatmo-koppeling
|
||||||
|
|
||||||
|
1. Maak een app aan op <https://dev.netatmo.com>. Zet `client_id` en `client_secret` in `config.php`.
|
||||||
|
2. Genereer met de token generator op de app-pagina een token met scope `read_station`.
|
||||||
|
3. Sla de refresh token op:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php bin/netatmo-init.php '<refresh_token>'
|
||||||
|
```
|
||||||
|
|
||||||
|
Dat schrijft `storage/netatmo-token.json` (mode 600). Bij het eerste verzoek wordt het access token ververst.
|
||||||
|
De refresh token roteert bij elke verversing; de nieuwste wordt automatisch bewaard. Gebruik een oude nooit opnieuw.
|
||||||
|
|
||||||
|
Toont het scherm "Netatmo-koppeling verlopen", genereer dan een nieuwe token en voer stap 3 opnieuw uit.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer test # PHPUnit: mapping, regenberekening, tokenrotatie, cache, stale-fallback
|
||||||
|
npm test # node --test: formattering, WMO-mapping, service worker
|
||||||
|
```
|
||||||
|
|
||||||
|
## Lokaal draaien
|
||||||
|
|
||||||
|
Snel, zonder Docker:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php -S 127.0.0.1:8080 -t public
|
||||||
|
```
|
||||||
|
|
||||||
|
Open <http://127.0.0.1:8080/>. Met `data_source = fixture` is er geen koppeling nodig.
|
||||||
|
Visuele check: een browservenster van exact 1133 × 744 naast de mockup (tab A).
|
||||||
|
|
||||||
|
Via de OrbStack shared-Apache-setup (`weerscherm.test`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# eenmalig: hostnaam
|
||||||
|
sudo sh -c 'echo "127.0.0.1 weerscherm.test" >> /etc/hosts'
|
||||||
|
# shared apache herstarten (vhost en mount staan al in orbstack/shared)
|
||||||
|
cd /Volumes/development/sites/orbstack/shared && docker-compose up -d --build
|
||||||
|
# php-container van dit project
|
||||||
|
cd /Volumes/development/sites/orbstack/divers/weerscherm && docker-compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
De bestanden staan in `orbstack/divers/weerscherm/` (Dockerfile, compose) en `orbstack/shared/apache/vhosts/weerscherm.conf`.
|
||||||
|
|
||||||
|
## Deploy (productie)
|
||||||
|
|
||||||
|
Productie-URL: `https://homedisplay.bahne-drei.de/`
|
||||||
|
|
||||||
|
- Git op de self-hosted Gitea, squash-and-merge naar `main`, deploy via DeployPad.
|
||||||
|
- Document root is `public/`. `src/`, `storage/`, `config.php` en `bin/` zijn dan niet via HTTP bereikbaar.
|
||||||
|
- `storage/` moet deploys overleven: maak er in DeployPad een gedeelde map van (shared folder) of zet
|
||||||
|
`storage_path` in `config.php` naar een map buiten de release-map, bijvoorbeeld `/var/www/weerscherm-storage`.
|
||||||
|
De map moet schrijfbaar zijn voor de webserver-gebruiker (`www-data`).
|
||||||
|
- `config.php` is per omgeving en staat niet in git; zet hem ook in de gedeelde map en symlink, of maak hem
|
||||||
|
eenmalig aan in de release-root.
|
||||||
|
- `composer install` is op de server niet nodig: `src/autoload.php` laadt de klassen zelf als `vendor/` ontbreekt.
|
||||||
|
- HTTPS is vereist voor de service worker en "Zet op beginscherm".
|
||||||
|
- Na de eerste deploy: `php bin/netatmo-init.php '<refresh_token>'` op de server, en controleer
|
||||||
|
`https://homedisplay.bahne-drei.de/api/data.php` op `"errors": []`.
|
||||||
|
- De app staat bewust zonder login. Kies een niet-voor-de-hand-liggend (sub)domein; `robots.txt` en
|
||||||
|
`X-Robots-Tag: noindex` houden zoekmachines buiten de deur.
|
||||||
|
|
||||||
|
Nieuwe versie van de frontend? Verhoog `VERSION` in `public/sw.js`; de app herlaadt zichzelf bij `controllerchange`
|
||||||
|
en in elk geval dagelijks rond 04:00.
|
||||||
|
|
||||||
|
## iPad-instellingen
|
||||||
|
|
||||||
|
1. Open de URL in Safari, tik op Delen → **Zet op beginscherm**. Start de app daarna altijd vanaf het beginscherm
|
||||||
|
(fullscreen, zonder Safari-balken).
|
||||||
|
2. Instellingen → Scherm en helderheid → **Automatisch vergrendelen → Nooit**.
|
||||||
|
3. Optioneel: Instellingen → Toegankelijkheid → **Begeleide toegang** inschakelen en starten met drie keer op de
|
||||||
|
zijknop, zodat het scherm niet per ongeluk verlaten wordt.
|
||||||
|
4. Houd de iPad liggend; in portretstand verschijnt "Draai de iPad een kwartslag".
|
||||||
|
|
||||||
|
## Gedrag bij storingen
|
||||||
|
|
||||||
|
| Situatie | Wat het scherm doet |
|
||||||
|
|---|---|
|
||||||
|
| Meting ouder dan 30 minuten of Netatmo tijdelijk onbereikbaar | "meting HH:MM · verouderd" in oranje, laatste data blijft staan |
|
||||||
|
| Server of wifi onbereikbaar | laatste data blijft staan, kopregel toont "geen verbinding sinds HH:MM"; herstelt vanzelf |
|
||||||
|
| Refresh token ongeldig (`netatmo_auth`) | melding over de bovenzone met de herstelinstructie |
|
||||||
|
| Open-Meteo onbereikbaar | laatst gecachte verwachting, `forecast_stale: true` |
|
||||||
|
| Allereerste start zonder data | "Gegevens laden…", daarna een concrete foutmelding |
|
||||||
|
|
||||||
|
## Acceptatiecriteria (spec §11)
|
||||||
|
|
||||||
|
- [ ] Op de iPad mini, gestart vanaf het beginscherm, draait de app fullscreen en klopt de layout met ontwerp A.
|
||||||
|
- [ ] Alle waarden komen overeen met de Netatmo-app: buiten, 3× binnen, min/max met tijdstippen, regen vandaag,
|
||||||
|
de afgelopen 3 dagen en het maandtotaal.
|
||||||
|
- [ ] De verwachting toont 5 dagen vanaf morgen met het juiste icoon per WMO-code.
|
||||||
|
- [ ] De data ververst zichzelf. Na middernacht staat de nieuwe datum er binnen 5 minuten.
|
||||||
|
- [ ] Wifi uit: de laatste data blijft staan met "geen verbinding sinds". Wifi aan: herstelt vanzelf.
|
||||||
|
- [ ] De Netatmo-token ververst meerdere dagen achter elkaar zonder handmatig ingrijpen.
|
||||||
|
- [ ] Geen secrets in git, in de browser of in responses. `storage/` is niet via HTTP bereikbaar.
|
||||||
|
- [ ] `composer test` en `npm test` slagen.
|
||||||
|
|
||||||
|
## Structuur
|
||||||
|
|
||||||
|
```
|
||||||
|
public/ document root: index.html, styles.css, app.js, format.js, icons.js, sw.js, manifest, icons/, api/data.php
|
||||||
|
src/ Config, Http, TokenStore, NetatmoClient, OpenMeteoClient, Cache, mappers, DashboardService
|
||||||
|
bin/ netatmo-init.php
|
||||||
|
storage/ tokens en cache (niet in git, niet in docroot)
|
||||||
|
tests/ PHPUnit + JSON-fixtures; tests/js voor node --test
|
||||||
|
docs/ spec, mockup, plan
|
||||||
|
```
|
||||||
@@ -16,7 +16,7 @@ declare(strict_types=1);
|
|||||||
use Weerscherm\Config;
|
use Weerscherm\Config;
|
||||||
use Weerscherm\TokenStore;
|
use Weerscherm\TokenStore;
|
||||||
|
|
||||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
require dirname(__DIR__) . '/src/autoload.php';
|
||||||
|
|
||||||
$refresh = $argv[1] ?? '';
|
$refresh = $argv[1] ?? '';
|
||||||
$access = $argv[2] ?? '';
|
$access = $argv[2] ?? '';
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# Alleen relevant als de productieserver AllowOverride toestaat. De vhost-config heeft voorrang.
|
||||||
|
<IfModule mod_headers.c>
|
||||||
|
Header set X-Robots-Tag "noindex, nofollow"
|
||||||
|
<FilesMatch "\.(html|js|css|webmanifest)$">
|
||||||
|
Header set Cache-Control "no-cache"
|
||||||
|
</FilesMatch>
|
||||||
|
</IfModule>
|
||||||
|
<IfModule mod_mime.c>
|
||||||
|
AddType application/manifest+json .webmanifest
|
||||||
|
</IfModule>
|
||||||
|
Options -Indexes
|
||||||
+1
-1
@@ -14,7 +14,7 @@ header('Content-Type: application/json; charset=utf-8');
|
|||||||
header('Cache-Control: no-store');
|
header('Cache-Control: no-store');
|
||||||
header('X-Robots-Tag: noindex');
|
header('X-Robots-Tag: noindex');
|
||||||
|
|
||||||
require $root . '/vendor/autoload.php';
|
require $root . '/src/autoload.php';
|
||||||
|
|
||||||
$configFile = $root . '/config.php';
|
$configFile = $root . '/config.php';
|
||||||
if (!is_file($configFile)) {
|
if (!is_file($configFile)) {
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Autoloader: Composer als die er is (nodig voor PHPUnit), anders een minimale PSR-4-lader voor src/.
|
||||||
|
* Zo werkt een deploy ook zonder `composer install`; er zijn immers geen runtime-dependencies.
|
||||||
|
*/
|
||||||
|
$composer = dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
if (is_file($composer)) {
|
||||||
|
require $composer;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spl_autoload_register(static function (string $class): void {
|
||||||
|
$prefix = 'Weerscherm\\';
|
||||||
|
if (!str_starts_with($class, $prefix)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$file = __DIR__ . '/' . str_replace('\\', '/', substr($class, strlen($prefix))) . '.php';
|
||||||
|
if (is_file($file)) {
|
||||||
|
require $file;
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user