From ce6e35cf3cd9548a5755f0f5dee3c99b3b7e2f43 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Wed, 21 May 2025 20:16:47 +0530 Subject: [PATCH 1/2] Update path --- CONTRIBUTING.md | 2 +- docs/add-new-adapter.md | 215 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 docs/add-new-adapter.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dde77db..46e6038 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -78,7 +78,7 @@ This is also important for the Utopia-php lead developers to be able to give tec ## Adding A New Adapter -You can follow our [Adding new Detector Adapter](docs/add-new-detector-adapter.md) tutorial to add a new Detector adapter. +You can follow our [Adding new Detector Adapter](docs/add-new-adapter.md) tutorial to add a new Detector adapter. ## Other Ways to Help diff --git a/docs/add-new-adapter.md b/docs/add-new-adapter.md new file mode 100644 index 0000000..c819997 --- /dev/null +++ b/docs/add-new-adapter.md @@ -0,0 +1,215 @@ +# Add new Detector and Detection Adapters + +To get started with implementing a new detector and detection adapters, start by reviewing the [README](/README.md) to understand the goals of this library. โค + +### Introduction ๐Ÿ“ +- A `Detector` is a class that analyzes input files to identify specific characteristics of a project. +- A `Detection` class represents a specific type of detection (like Framework, Runtime, Packager, etc.) and contains the logic for identifying that type. +- To add a new detector, you need to extend the `Detector` parent class and define the required methods. +- To add a new detection class, you need to extend the appropriate `Detection` parent class (Framework, Runtime, Packager, or Rendering). + +### File Structure ๐Ÿ“‚ + +Below are outlined the most useful files for adding a new detector and detection class: + +```bash +. +โ”œโ”€โ”€ src # Source code +โ”‚ โ”œโ”€โ”€ Detector.php # Parent class for all detectors +โ”‚ โ”œโ”€โ”€ Detection.php # Parent class for all detections +โ”‚ โ”œโ”€โ”€ Detector/ # Where your new detector goes! +โ”‚ โ”‚ โ”œโ”€โ”€ Framework.php # Framework detector +โ”‚ โ”‚ โ”œโ”€โ”€ Packager.php # Packager detector +โ”‚ โ”‚ โ”œโ”€โ”€ Runtime.php # Runtime detector +โ”‚ โ”‚ โ””โ”€โ”€ Rendering.php # Rendering detector +โ”‚ โ””โ”€โ”€ Detection/ # Where your new detection class goes! +โ”‚ โ”œโ”€โ”€ Framework/ # Framework detections +โ”‚ โ”œโ”€โ”€ Packager/ # Packager detections +โ”‚ โ”œโ”€โ”€ Runtime/ # Runtime detections +โ”‚ โ””โ”€โ”€ Rendering/ # Rendering detections +โ””โ”€โ”€ tests + โ””โ”€โ”€ unit/ # Where tests for your new detector/detection go! +``` + +### Extend the Detector ๐Ÿ’ป + +Create your new detector file in `src/Detector` and extend the parent class: + +```php + + */ + protected array $options = []; + + /** + * @param array $inputs + */ + public function __construct(protected array $inputs) + { + } + + public function detect(): ?YourDetection + { + foreach ($this->options as $detector) { + $detectorFiles = $detector->getFiles(); + $matches = array_intersect($detectorFiles, $this->inputs); + + if (count($matches) > 0) { + return $detector; + } + } + + return null; + } +} +``` + +### Extend the Detection Class ๐Ÿ’ป + +Create your new detection class in the appropriate directory under `src/Detection` and extend the parent class: + +```php + + */ + public function getFiles(): array + { + return ['file1.ext', 'file2.ext']; + } + + // Implement other required methods based on parent class +} +``` + +### Testing ๐Ÿงช + +Add tests for your new detector and detection class in `tests/unit/DetectorTest.php`. Here's an example: + +```php +public function testYourDetector(array $files, ?string $expectedName): void +{ + $detector = new YourDetector($files); + $detector->addOption(new YourDetection()); + + $detected = $detector->detect(); + + if ($expectedName) { + $this->assertNotNull($detected); + $this->assertEquals($expectedName, $detected->getName()); + } else { + $this->assertNull($detected); + } +} + +/** + * @return array, string|null}> + */ +public function yourDetectorDataProvider(): array +{ + return [ + [['file1.ext', 'file2.ext'], 'your-detection-name'], + [['other.ext'], null], + ]; +} +``` + +### Tips and Tricks ๐Ÿ’ก + +1. **Choose the Right Parent Class** + - For framework detection: Extend `Detection\Framework` + - For runtime detection: Extend `Detection\Runtime` + - For packager detection: Extend `Detection\Packager` + - For rendering detection: Extend `Detection\Rendering` + +2. **Implement Required Methods** + - Each detection type has specific required methods + - Framework detections need: `getName()`, `getFiles()`, `getInstallCommand()`, `getBuildCommand()`, `getOutputDirectory()` + - Runtime detections need: `getName()`, `getLanguages()`, `getFileExtensions()`, `getFiles()`, `getCommands()`, `getEntrypoint()` + - Packager detections need: `getName()`, `getFiles()` + - Rendering detections need: `getName()` + +3. **File Detection** + - Use specific file patterns that uniquely identify your detection + - Consider both common and edge cases + - Include configuration files, lock files, and other distinctive files + +4. **Testing** + - Test both positive and negative cases + - Include edge cases in your test data + - Follow the existing test patterns in the codebase + +5. **Performance** + - Keep detection logic simple and efficient + - Minimize file system operations + - Use array operations for file matching + +### Example Implementation + +Here's a complete example of implementing a new framework detection: + +```php + + */ + public function getFiles(): array + { + return ['my-framework.config.js', 'my-framework.lock']; + } + + public function getInstallCommand(): string + { + return 'npm install'; + } + + public function getBuildCommand(): string + { + return 'npm run build'; + } + + public function getOutputDirectory(): string + { + return './dist'; + } +} +``` + +Only include dependencies strictly necessary for the adapter, preferably official PHP libraries, if available. + +### Testing with Docker ๐Ÿ› ๏ธ + +The existing test suite is helpful when developing a new Detector/ Detection adapter. Use official Docker images from trusted sources. Add new tests for your new Detector/ Detection adapter in `tests/unit/DetectorTest.php` test class. The specific `docker-compose` command for testing can be found in the [README](/README.md#tests). \ No newline at end of file From 18c9510af59e7f1db88530595558cc6603b17676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 25 Jun 2025 16:44:45 +0200 Subject: [PATCH 2/2] Update docs/add-new-adapter.md --- docs/add-new-adapter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/add-new-adapter.md b/docs/add-new-adapter.md index c819997..3094299 100644 --- a/docs/add-new-adapter.md +++ b/docs/add-new-adapter.md @@ -1,6 +1,6 @@ # Add new Detector and Detection Adapters -To get started with implementing a new detector and detection adapters, start by reviewing the [README](/README.md) to understand the goals of this library. โค +To get started with implementing a new detector and detection adapters, start by reviewing the [README](/README.md) to understand the goals of this library. ### Introduction ๐Ÿ“ - A `Detector` is a class that analyzes input files to identify specific characteristics of a project.