Skip to content

Commit f7dfff9

Browse files
authored
Merge pull request #73 from ray-di/feature/media-query-sql-module
Add MediaQuerySqlModule for simplified API (1.0 preparation)
2 parents 6becf87 + 1b38df6 commit f7dfff9

File tree

5 files changed

+160
-2
lines changed

5 files changed

+160
-2
lines changed

src/MediaQueryBaseModule.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212
use Ray\InputQuery\ToArray;
1313
use Ray\InputQuery\ToArrayInterface;
1414

15+
/**
16+
* Base module for MediaQuery framework - provides common bindings.
17+
*
18+
* This is an internal implementation module. Users should use MediaQuerySqlModule
19+
* or MediaQueryWebModule instead of using this module directly.
20+
*
21+
* @internal
22+
*/
1523
final class MediaQueryBaseModule extends AbstractModule
1624
{
1725
public function __construct(

src/MediaQueryDbModule.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
use Ray\MediaQuery\Annotation\Qualifier\FactoryMethod;
1111
use Ray\MediaQuery\Annotation\Qualifier\SqlDir;
1212

13+
/**
14+
* Database query module - provides SQL-specific bindings.
15+
*
16+
* This is an internal implementation module. Users should use MediaQuerySqlModule
17+
* instead of using this module directly.
18+
*
19+
* @internal
20+
*/
1321
final class MediaQueryDbModule extends AbstractModule
1422
{
1523
public function __construct(

src/MediaQueryModule.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,32 @@
77
use Override;
88
use Ray\Di\AbstractModule;
99

10+
/**
11+
* Low-level MediaQuery module for advanced configurations.
12+
*
13+
* This is an internal/advanced API. For most use cases, use MediaQuerySqlModule instead.
14+
*
15+
* MediaQuerySqlModule provides a simpler interface:
16+
* ```php
17+
* // Recommended: Simple and clear
18+
* $this->install(new MediaQuerySqlModule('/path/to/interfaces', '/path/to/sql'));
19+
*
20+
* // Advanced: When you need Queries::fromClasses() or other customization
21+
* $queries = Queries::fromClasses([UserInterface::class, OrderInterface::class]);
22+
* $this->install(new MediaQueryModule($queries, [new DbQueryConfig('/path/to/sql')]));
23+
* ```
24+
*
25+
* Note: The array of DbQueryConfig currently only uses the last element.
26+
* Multiple SQL directories may be supported in future versions if needed.
27+
*
28+
* @internal This is a low-level API. Use MediaQuerySqlModule for typical use cases.
29+
*/
1030
final class MediaQueryModule extends AbstractModule
1131
{
1232
/** @param list<DbQueryConfig> $configs */
1333
public function __construct(
14-
private Queries $queries,
15-
private array $configs,
34+
private readonly Queries $queries,
35+
private readonly array $configs,
1636
AbstractModule|null $module = null,
1737
) {
1838
parent::__construct($module);
@@ -22,6 +42,7 @@ public function __construct(
2242
protected function configure(): void
2343
{
2444
$this->install(new MediaQueryBaseModule($this->queries));
45+
// Note: Only the last config in the array is effective due to binding overwrite
2546
foreach ($this->configs as $config) {
2647
$this->install(new MediaQueryDbModule($config));
2748
}

src/MediaQuerySqlModule.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Ray\MediaQuery;
6+
7+
use Override;
8+
use Ray\Di\AbstractModule;
9+
10+
/**
11+
* SQL-based MediaQuery module.
12+
*
13+
* This module simplifies SQL query integration by accepting directory paths directly.
14+
* It automatically discovers query interfaces from the interface directory and configures
15+
* SQL query execution from the SQL directory.
16+
*
17+
* Example usage:
18+
* ```php
19+
* $this->install(new MediaQuerySqlModule(
20+
* interfaceDir: '/path/to/query/interfaces',
21+
* sqlDir: '/path/to/sql/files'
22+
* ));
23+
* ```
24+
*
25+
* For advanced use cases requiring explicit query class selection or custom configuration,
26+
* create your own module that wraps the internal modules:
27+
* ```php
28+
* class MyQueryModule extends AbstractModule {
29+
* protected function configure(): void {
30+
* $queries = Queries::fromClasses([UserInterface::class, OrderInterface::class]);
31+
* $this->install(new MediaQueryBaseModule($queries));
32+
* $this->install(new MediaQueryDbModule(new DbQueryConfig('/path/to/sql')));
33+
* }
34+
* }
35+
* ```
36+
*/
37+
final class MediaQuerySqlModule extends AbstractModule
38+
{
39+
public function __construct(
40+
private readonly string $interfaceDir,
41+
private readonly string $sqlDir,
42+
AbstractModule|null $module = null,
43+
) {
44+
parent::__construct($module);
45+
}
46+
47+
#[Override]
48+
protected function configure(): void
49+
{
50+
$queries = Queries::fromDir($this->interfaceDir);
51+
$this->install(new MediaQueryBaseModule($queries));
52+
$this->install(new MediaQueryDbModule(new DbQueryConfig($this->sqlDir)));
53+
}
54+
}

tests/MediaQuerySqlModuleTest.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Ray\MediaQuery;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Ray\AuraSqlModule\AuraSqlModule;
9+
use Ray\Di\AbstractModule;
10+
use Ray\Di\Injector;
11+
12+
class MediaQuerySqlModuleTest extends TestCase
13+
{
14+
public function testModuleCanBeInstalled(): void
15+
{
16+
$module = new class extends AbstractModule {
17+
protected function configure(): void
18+
{
19+
$this->install(new MediaQuerySqlModule(
20+
__DIR__ . '/Fake/Queries',
21+
__DIR__ . '/sql',
22+
));
23+
$this->install(new AuraSqlModule('sqlite::memory:'));
24+
}
25+
};
26+
27+
$injector = new Injector($module);
28+
// Test that basic services are bound
29+
$logger = $injector->getInstance(MediaQueryLoggerInterface::class);
30+
$this->assertInstanceOf(MediaQueryLoggerInterface::class, $logger);
31+
}
32+
33+
public function testSimplifiedApiComparedToOldWay(): void
34+
{
35+
// New simplified API
36+
$newModule = new class extends AbstractModule {
37+
protected function configure(): void
38+
{
39+
$this->install(new MediaQuerySqlModule(
40+
__DIR__ . '/Fake/Queries',
41+
__DIR__ . '/sql',
42+
));
43+
$this->install(new AuraSqlModule('sqlite::memory:'));
44+
}
45+
};
46+
47+
// Old verbose API (deprecated)
48+
$oldModule = new class extends AbstractModule {
49+
protected function configure(): void
50+
{
51+
$queries = Queries::fromDir(__DIR__ . '/Fake/Queries');
52+
$this->install(new MediaQueryModule($queries, [new DbQueryConfig(__DIR__ . '/sql')]));
53+
$this->install(new AuraSqlModule('sqlite::memory:'));
54+
}
55+
};
56+
57+
// Both should bind the same basic services
58+
$newInjector = new Injector($newModule);
59+
$oldInjector = new Injector($oldModule);
60+
61+
$newLogger = $newInjector->getInstance(MediaQueryLoggerInterface::class);
62+
$oldLogger = $oldInjector->getInstance(MediaQueryLoggerInterface::class);
63+
64+
$this->assertInstanceOf(MediaQueryLoggerInterface::class, $newLogger);
65+
$this->assertInstanceOf(MediaQueryLoggerInterface::class, $oldLogger);
66+
}
67+
}

0 commit comments

Comments
 (0)