Skip to content

Commit

Permalink
feat: configurable base directory for bundles
Browse files Browse the repository at this point in the history
  • Loading branch information
trivoallan committed Nov 2, 2024
1 parent b6f820b commit feb839d
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 149 deletions.
172 changes: 37 additions & 135 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Le package `AssetGatherer` permet de collecter des ressources (images, CSS, Java
- [Diagramme de Conteneur](#diagramme-de-conteneur)

Check notice on line 11 in README.md

View workflow job for this annotation

GitHub Actions / Trunk Check

markdownlint(MD051)

[new] Link fragments should be valid
- [Diagramme de Composant](#diagramme-de-composant)

Check notice on line 12 in README.md

View workflow job for this annotation

GitHub Actions / Trunk Check

markdownlint(MD051)

[new] Link fragments should be valid
- [Utilisation avec PSR-7](#utilisation-avec-psr-7)
- [Utilisation avec Répertoire de Base](#utilisation-avec-répertoire-de-base)
- [Utilisation du Dev Container](#utilisation-du-dev-container)
- [Exécution des Tests](#exécution-des-tests)

Expand All @@ -37,88 +38,56 @@ La configuration du package `AssetGatherer` se fait via un fichier YAML. Chaque
# config/bundles.yaml
homepage:
images:
directories: ["path/to/homepage/images"]
directories: ["homepage/images"]
extensions: ["jpg", "png"]
css:
directories: ["path/to/homepage/css"]
directories: ["homepage/css"]
extensions: ["css"]
rules:
pathContains: "/homepage"

dashboard:
javascript:
directories: ["path/to/dashboard/js"]
directories: ["dashboard/js"]
extensions: ["js"]
rules:
query:
admin: "true"
```
## Diagrammes C4
## Utilisation avec Répertoire de Base
### Diagramme de Contexte
Le package `AssetGatherer` prend en charge un répertoire de base pour les _bundles_. En définissant un répertoire de base, tous les chemins spécifiés dans la configuration YAML sont interprétés comme étant relatifs à ce répertoire.

```mermaid
C4Context
title System Context Diagram for AssetGatherer
### Exemple d’Utilisation avec Répertoire de Base

Person(dev, "Développeur", "Un développeur utilisant le package pour gérer des ressources conditionnelles dans une application PHP")

System_Boundary(assetGatherer, "Package AssetGatherer") {
Component(assetGathererCore, "AssetGatherer", "Library", "Un package PHP qui permet de collecter des ressources conditionnelles basées sur des règles de requête HTTP")
}

System(api, "API HTTP", "API externe", "Reçoit les requêtes HTTP et fournit des informations pour la collecte des ressources")

Rel(dev, assetGathererCore, "Utilise", "Définit les règles de configuration et interagit avec le package")
Rel(assetGathererCore, api, "Extrait les informations de requête", "Utilise les paramètres de requête HTTP pour filtrer les ressources")

UpdateElementStyle(dev, $fontColor="black", $bgColor="#ffcc00")
UpdateElementStyle(assetGathererCore, $fontColor="black", $bgColor="#6fa8dc")
UpdateElementStyle(api, $fontColor="black", $bgColor="#93c47d")
```

### Diagramme de Conteneur

```mermaid
C4Container
title Container Diagram for AssetGatherer
```php
use AssetGatherer\AssetGatherer;
use Nyholm\Psr7\ServerRequest;
Person(dev, "Développeur", "Configure le package et définit les règles")
// Définissez un répertoire de base pour les fichiers d'assets
$baseDirectory = '/var/www/assets';
$assetGatherer = new AssetGatherer($baseDirectory);
$assetGatherer->loadConfiguration('config/bundles.yaml');
System_Boundary(app, "Application PHP") {
Container(appCode, "Code de l'Application", "PHP", "Application utilisant le package AssetGatherer pour collecter des ressources conditionnelles")
Container(assetGathererLib, "AssetGatherer", "Library", "Package PHP pour la collecte de ressources conditionnelles")
}
// Créez une requête HTTP PSR-7
$request = new ServerRequest('GET', '/homepage', [
'User-Agent' => 'Chrome',
'Accept' => 'text/html'
]);
Container(configFile, "Configuration YAML", "Fichier", "Fichier de configuration des règles de collection de ressources")
// Collectez les ressources en fonction de la requête
$assetGatherer->gatherAssetsForRequest($request);
Rel(dev, configFile, "Définit")
Rel(appCode, assetGathererLib, "Intègre et utilise")
Rel(assetGathererLib, configFile, "Charge et utilise")
// Récupérez et affichez les ressources collectées
$assets = $assetGatherer->getAssets();
print_r($assets);
```

### Diagramme de Composant
Dans cet exemple :

```mermaid
C4Component
title Component Diagram for AssetGatherer
Container_Boundary(assetGathererLib, "AssetGatherer") {
Component(configLoader, "Configuration Loader", "PHP", "Charge et analyse le fichier de configuration YAML")
Component(ruleEngine, "Rule Engine", "PHP", "Évalue les règles de collecte basées sur la requête")
Component(assetCollector, "Asset Collector", "PHP", "Collecte les ressources en fonction des règles évaluées")
}
Container(configFile, "Configuration YAML", "Fichier", "Fichier de configuration des règles de collection de ressources")
Container(httpRequest, "Requête HTTP", "HTTP", "Requête HTTP contenant les informations pour les règles")
Rel(configLoader, configFile, "Charge la configuration")
Rel(ruleEngine, configLoader, "Utilise")
Rel(assetCollector, ruleEngine, "Interroge et utilise")
Rel(ruleEngine, httpRequest, "Évalue les règles basées sur")
Rel(assetCollector, httpRequest, "Accède aux informations de la requête")
```
- **Répertoire de Base** : Le répertoire de base `/var/www/assets` est utilisé pour préfixer tous les chemins des répertoires définis dans `bundles.yaml`.
- **Collecte des Ressources** : Le package cherchera les fichiers dans les répertoires définis dans `bundles.yaml`, relatifs au répertoire de base.

## Utilisation avec PSR-7

Expand All @@ -132,17 +101,8 @@ Assurez-vous d'avoir une implémentation PSR-7 installée dans votre projet, par
composer require nyholm/psr7
```

### Chargement de la Configuration

```php
$assetGatherer = new AssetGatherer();
$assetGatherer->loadConfiguration('config/bundles.yaml');
```

### Création d'une Requête HTTP avec PSR-7

Pour collecter les ressources en fonction d'une requête HTTP, créez une instance de `ServerRequestInterface`.

```php
use Nyholm\Psr7\ServerRequest;
Expand All @@ -152,84 +112,26 @@ $request = new ServerRequest('GET', '/homepage', [
]);
```

### Collecte des Ressources

```php
$assetGatherer->gatherAssetsForRequest($request);
```

### Récupération des Ressources Collectées

```php
$allAssets = $assetGatherer->getAssets();
$homepageAssets = $assetGatherer->getAssets('homepage');
```
## Utilisation du Dev Container

### Exemple Complet
Le projet inclut une configuration de Dev Container pour un environnement de développement reproductible.

```php
use AssetGatherer\AssetGatherer;
use Nyholm\Psr7\ServerRequest;
### Prérequis

Check notice on line 119 in README.md

View workflow job for this annotation

GitHub Actions / Trunk Check

markdownlint(MD024)

[new] Multiple headings with the same content

$assetGatherer = new AssetGatherer();
$assetGatherer->loadConfiguration('config/bundles.yaml');
- **Docker** : Assurez-vous que Docker est installé et en cours d'exécution.
- **Visual Studio Code** : Utilisez l'extension "Remote - Containers".

$request = new ServerRequest('GET', '/homepage', [
'User-Agent' => 'Chrome',
'Accept' => 'text/html'
]);
### Démarrage du Dev Container

$assetGatherer->gatherAssetsForRequest($request);
$assets = $assetGatherer->getAssets();
print_r($assets);
```
1. **Ouvrez le projet dans Visual Studio Code**.
2. **Ouvrez le Dev Container** : Appuyez sur `F1`, tapez `Remote-Containers: Reopen in Container`, et sélectionnez cette option.

## Exécution des Tests

```bash
vendor/bin/phpunit tests/AssetGathererTest.php
```

## Utilisation du Dev Container

Le projet inclut une configuration de Dev Container pour fournir un environnement de développement reproductible et préconfiguré, idéal pour la collaboration et le développement en environnement isolé. Le Dev Container utilise Docker pour configurer une image avec PHP, Composer, et d'autres dépendances nécessaires pour travailler avec le package `AssetGatherer`.

### Avant de commencer

- **Docker** : Assurez-vous que Docker est installé et en cours d'exécution.
- **Visual Studio Code** : Utilisez l'extension "Remote - Containers" pour ouvrir et gérer le Dev Container.

### Démarrage du Dev Container

1. **Ouvrez le projet dans Visual Studio Code** : Assurez-vous que le dossier racine du projet est ouvert dans l'éditeur.
2. **Ouvrez le Dev Container** : Appuyez sur `F1`, tapez `Remote-Containers: Reopen in Container`, et sélectionnez cette option. VS Code va alors :
- Construire l'image Docker définie dans `.devcontainer/Dockerfile`.
- Démarrer le conteneur avec les outils et extensions configurés.
3. **Installez les dépendances** : Une fois le Dev Container démarré, les dépendances sont installées automatiquement via le `postCreateCommand` défini dans `.devcontainer/devcontainer.json`.

### Outils et Extensions Disponibles

Dans le Dev Container, les outils suivants sont préinstallés :

- **PHP** : Environnement PHP avec la version définie dans le Dockerfile.
- **Composer** : Gestionnaire de dépendances PHP.
- **PHPUnit** : Outil de test pour exécuter des tests unitaires.

### Exécution des Commandes dans le Dev Container

Une fois le Dev Container démarré, vous pouvez utiliser le terminal intégré de VS Code pour exécuter des commandes :

- **Exécuter les tests PHPUnit** : `phpunit`
- **Installer les dépendances Composer** : `composer install`

### Personnalisation

La configuration du Dev Container peut être personnalisée dans les fichiers `.devcontainer/devcontainer.json` et `.devcontainer/Dockerfile`. Par exemple, vous pouvez ajouter des dépendances supplémentaires, configurer des scripts supplémentaires dans `postCreateCommand`, ou installer d'autres extensions Visual Studio Code.

### Avantages du Dev Container

- **Environnement Reproductible** : Les configurations, dépendances, et outils sont identiques pour tous les développeurs travaillant sur le projet.
- **Isolation** : Le Dev Container fonctionne de manière isolée, ce qui évite les conflits de dépendances avec le système local.
- **Facilité de Configuration** : Tout est défini dans le projet, donc aucune configuration manuelle supplémentaire n'est nécessaire pour les nouveaux contributeurs.
---

Pour plus de détails sur les Dev Containers, consultez la [documentation officielle de Visual Studio Code](https://code.visualstudio.com/docs/remote/containers).
Cette documentation couvre l'installation, la configuration, l'utilisation, et les tests du package `AssetGatherer`.
17 changes: 13 additions & 4 deletions src/AssetGatherer.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@

class AssetGatherer
{
private $bundles = [];
private $gatheredAssets = [];
private array $bundles = [];
private array $gatheredAssets = [];
private string $baseDirectory = '';

public function __construct(string $baseDirectory = '')
{
$this->baseDirectory = rtrim($baseDirectory, '/');
}

public function loadConfiguration(string $yamlFilePath): void
{
Expand All @@ -29,8 +35,10 @@ public function gatherAssetsForRequest(ServerRequestInterface $request): void
foreach ($config as $type => $typeConfig) {
if ($type !== 'rules') {
foreach ($typeConfig['directories'] as $directory) {
if (is_dir($directory)) {
$this->scanDirectory($directory, $typeConfig['extensions'], $bundleName, $type);
// Préfixe le répertoire par `baseDirectory` si défini
$fullDirectoryPath = $this->baseDirectory ? $this->baseDirectory . '/' . $directory : $directory;
if (is_dir($fullDirectoryPath)) {
$this->scanDirectory($fullDirectoryPath, $typeConfig['extensions'], $bundleName, $type);
}
}
}
Expand Down Expand Up @@ -74,6 +82,7 @@ private function scanDirectory(string $directory, array $extensions, string $bun
{
$directoryIterator = new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS);
$iterator = new \RecursiveIteratorIterator($directoryIterator);

foreach ($iterator as $file) {
if (in_array($file->getExtension(), $extensions, true)) {
if (!isset($this->gatheredAssets[$bundleName][$type])) {
Expand Down
33 changes: 23 additions & 10 deletions tests/AssetGathererTest.php
Original file line number Diff line number Diff line change
@@ -1,39 +1,52 @@
<?php

use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7\ServerRequest;
use PHPUnit\Framework\TestCase;
use AssetGatherer\AssetGatherer;

class AssetGathererTest extends TestCase
{
private $assetGatherer;
private $baseDirectory;

Check failure on line 10 in tests/AssetGathererTest.php

View workflow job for this annotation

GitHub Actions / Trunk Check

phpstan(phpstan)

[new] Property AssetGathererTest::$baseDirectory has no type specified.

protected function setUp(): void
{
$this->assetGatherer = new AssetGatherer();
$this->baseDirectory = __DIR__ . '/assets'; // Définir un répertoire de base pour les tests
mkdir($this->baseDirectory . '/homepage/images', 0777, true);
file_put_contents($this->baseDirectory . '/homepage/images/test.jpg', 'image content');

// Instancier AssetGatherer avec un répertoire de base
$this->assetGatherer = new AssetGatherer($this->baseDirectory);
$this->assetGatherer->loadConfiguration(__DIR__ . '/../config/bundles.yaml');
}

public function testGatherAssetsForHomepageRequest(): void
protected function tearDown(): void
{
$factory = new Psr17Factory();
$request = new ServerRequest('GET', '/homepage');
// Nettoyer les fichiers et dossiers de test créés
unlink($this->baseDirectory . '/homepage/images/test.jpg');
rmdir($this->baseDirectory . '/homepage/images');
rmdir($this->baseDirectory . '/homepage');
}

public function testGatherAssetsWithBaseDirectory(): void
{
$request = new ServerRequest('GET', '/homepage');
$this->assetGatherer->gatherAssetsForRequest($request);
$assets = $this->assetGatherer->getAssets('homepage');

$assets = $this->assetGatherer->getAssets('homepage');

// Vérifier que le fichier est collecté en utilisant le répertoire de base
$this->assertArrayHasKey('images', $assets);
$this->assertCount(1, $assets['images']);

Check failure on line 40 in tests/AssetGathererTest.php

View workflow job for this annotation

GitHub Actions / Trunk Check

phpstan(phpstan)

[new] Call to an undefined method AssetGathererTest::assertCount().
$this->assertStringContainsString('test.jpg', $assets['images'][0]);

Check failure on line 41 in tests/AssetGathererTest.php

View workflow job for this annotation

GitHub Actions / Trunk Check

phpstan(phpstan)

[new] Call to an undefined method AssetGathererTest::assertStringContainsString().
}

public function testNoAssetsForNonMatchingRequest(): void
{
$factory = new Psr17Factory();
$request = new ServerRequest('GET', '/unknown');

$request = new ServerRequest('GET', '/nonexistent');
$this->assetGatherer->gatherAssetsForRequest($request);
$assets = $this->assetGatherer->getAssets();

$assets = $this->assetGatherer->getAssets();
$this->assertEmpty($assets);
}
}

0 comments on commit feb839d

Please sign in to comment.