Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Chg #83: Bump PHP minimal version to 8.1 (@vjik)
- Chg #81, #83: Change PHP constraint in `composer.json` to `8.1 - 8.4` (@vjik)
- New #84: Add `AliasReference` (@vjik)

## 3.0.0 February 13, 2023

Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,23 @@ $aliases = new Aliases([
$aliases->remove('@root');
```

### Alias references

The package provides `AliasReference` class that implements `ReferenceInterface` from
[Yii Definition](https://github.com/yiisoft/definitions). It allows you to create references to aliases
that will be resolved at runtime:

```php
// Create a reference to an alias
$reference = \Yiisoft\Aliases\AliasReference::to('@public/assets');

// The reference will be resolved when needed
$configPath = $reference->resolve($container);
```

This is particularly useful in dependency injection configurations where you want to inject resolved paths
but the aliases are not available at configuration time.

## Documentation

- [Internals](docs/internals.md)
Expand Down
18 changes: 18 additions & 0 deletions composer-require-checker.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"symbol-whitelist": [
"Psr\\Container\\ContainerInterface",
"Yiisoft\\Definitions\\Contract\\ReferenceInterface"
],
"php-core-extensions": [
"Core",
"date",
"json",
"pcre",
"Phar",
"Reflection",
"SPL",
"standard",
"fileinfo"
],
"scan-files": []
}
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,14 @@
"require-dev": {
"maglnet/composer-require-checker": "^4.7.1",
"phpunit/phpunit": "^10.5.48",
"psr/container": "^2.0.2",
"rector/rector": "^2.1.2",
"roave/infection-static-analysis-plugin": "^1.35",
"spatie/phpunit-watcher": "^1.24.0",
"vimeo/psalm": "^5.26.1 || ^6.13",
"yiisoft/di": "^1.4"
"yiisoft/definitions": "^3.4",
"yiisoft/di": "^1.4",
"yiisoft/test-support": "^3.0.2"
},
"autoload": {
"psr-4": {
Expand All @@ -49,7 +52,6 @@
},
"config": {
"sort-packages": true,
"bump-after-update": "dev",
"allow-plugins": {
"infection/extension-installer": true,
"composer/package-versions-deprecated": true
Expand Down
1 change: 1 addition & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
errorLevel="1"
findUnusedBaselineEntry="true"
findUnusedCode="false"
ensureOverrideAttribute="false"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
Expand Down
61 changes: 61 additions & 0 deletions src/AliasReference.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Aliases;

use InvalidArgumentException;
use Psr\Container\ContainerInterface;
use Yiisoft\Definitions\Contract\ReferenceInterface;

use function is_string;

/**
* Reference to an alias that will be resolved at runtime.
*/
final class AliasReference implements ReferenceInterface
{
/**
* @var string The alias to be resolved.
*/
private string $alias;

/**
* @param string $alias The alias to be resolved.
*/
private function __construct(string $alias)
{
$this->alias = $alias;
}

/**
* Creates a new alias reference.
*
* @param string $id The alias to be resolved.
*
* @return self An instance of reference.
*
* @psalm-suppress MoreSpecificImplementedParamType, DocblockTypeContradiction
*/
public static function to(mixed $id): self
{
if (!is_string($id)) {
throw new InvalidArgumentException('Alias must be a string.');
}
return new self($id);
}

/**
* Retrieves {@see Aliases} from the container and uses it to resolve the alias to its actual path.
*
* @param ContainerInterface $container The DI container.
*
* @return string The resolved path for the alias.
*/
public function resolve(ContainerInterface $container): string
{
/** @var Aliases $aliases */
$aliases = $container->get(Aliases::class);
return $aliases->get($this->alias);
}
}
56 changes: 56 additions & 0 deletions tests/AliasReferenceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Aliases\Tests;

use InvalidArgumentException;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
use stdClass;
use Yiisoft\Aliases\AliasReference;
use Yiisoft\Aliases\Aliases;
use Yiisoft\Test\Support\Container\SimpleContainer;

use function PHPUnit\Framework\assertSame;

final class AliasReferenceTest extends TestCase
{
#[TestWith(['/path/to/app', '@app'])]
#[TestWith(['/path/to/app/runtime/logs', '@runtime/logs'])]
#[TestWith(['/test/path', '/test/path'])]
public function testResolve(string $expected, string $alias): void
{
$container = new SimpleContainer([
Aliases::class => new Aliases([
'@app' => '/path/to/app',
'@runtime' => '@app/runtime',
]),
]);

$reference = AliasReference::to($alias);

assertSame($expected, $reference->resolve($container));
}

public static function dataInvalidValue(): array
{
return [
'int' => [123],
'null' => [null],
'array' => [['@app']],
'object' => [new stdClass()],
'float' => [12.3],
'boolean' => [true],
];
}

#[DataProvider('dataInvalidValue')]
public function testInvalidValue(mixed $value): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Alias must be a string.');
AliasReference::to($value);
}
}
Loading