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
6 changes: 3 additions & 3 deletions packages/database/src/Builder/ModelInspector.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public function getBelongsTo(string $name): ?BelongsTo

$singularizedName = $name->singularizeLastWord();

if (! $singularizedName->equals($name)) {
if (! $singularizedName->equals($name) && $this->reflector->hasProperty($singularizedName)) {
return $this->getBelongsTo($singularizedName);
}

Expand Down Expand Up @@ -264,7 +264,7 @@ public function getHasOne(string $name): ?HasOne

$singularizedName = $name->singularizeLastWord();

if (! $singularizedName->equals($name)) {
if (! $singularizedName->equals($name) && $this->reflector->hasProperty($singularizedName)) {
return $this->getHasOne($singularizedName);
}

Expand Down Expand Up @@ -343,7 +343,7 @@ public function getHasOneThrough(string $name): ?HasOneThrough

$singularizedName = $name->singularizeLastWord();

if (! $singularizedName->equals($name)) {
if (! $singularizedName->equals($name) && $this->reflector->hasProperty($singularizedName)) {
return $this->getHasOneThrough($singularizedName);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/intl/src/Pluralizer/InflectorPluralizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ private function extractLastWord(string $value, ?string &$prefix = null, ?string
? array_pop(array: $parts)
: '';

if (count(value: $parts) === 0) {
if ($parts === []) {
return null;
}

Expand Down
127 changes: 127 additions & 0 deletions tests/Integration/Database/ModelInspector/LatinPluralRelationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<?php

namespace Tests\Tempest\Integration\Database\ModelInspector;

use PHPUnit\Framework\Attributes\Test;
use Tempest\Database\BelongsTo;
use Tempest\Database\Config\DatabaseDialect;
use Tempest\Database\HasOne;
use Tempest\Database\HasOneThrough;
use Tempest\Database\PrimaryKey;
use Tempest\Database\Table;
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;

use function Tempest\Database\inspect;

final class LatinPluralRelationTest extends FrameworkIntegrationTestCase
{
#[Test]
public function belongs_to_with_latin_plural_property_name(): void
{
$model = inspect(model: LatinPluralProductModel::class);
$relation = $model->getRelation(name: 'product_metadata');

$this->assertInstanceOf(
expected: BelongsTo::class,
actual: $relation,
);

$this->assertSame(
expected: 'LEFT JOIN metadata ON metadata.id = products.metadata_id',
actual: $relation
->getJoinStatement()
->compile(dialect: DatabaseDialect::SQLITE),
);
}

#[Test]
public function has_one_with_latin_plural_property_name(): void
{
$model = inspect(model: LatinPluralMetadataModel::class);
$relation = $model->getRelation(name: 'extra_data');

$this->assertInstanceOf(
expected: HasOne::class,
actual: $relation,
);
}

#[Test]
public function has_one_through_with_latin_plural_property_name(): void
{
$model = inspect(model: LatinPluralMetadataModel::class);
$relation = $model->getRelation(name: 'product_criteria');

$this->assertInstanceOf(
expected: HasOneThrough::class,
actual: $relation,
);
}

#[Test]
public function latin_plural_belongs_to_uses_fk_in_select_fields(): void
{
$model = inspect(model: LatinPluralProductModel::class);
$fields = $model->getSelectFields()->toArray();

$this->assertContains(
needle: 'metadata_id',
haystack: $fields,
);
$this->assertNotContains(
needle: 'product_metadata',
haystack: $fields,
);
}
}

#[Table(name: 'products')]
final class LatinPluralProductModel
{
public PrimaryKey $id;

#[BelongsTo]
public ?LatinPluralMetadataModel $product_metadata = null;

public string $name;
}

#[Table(name: 'metadata')]
final class LatinPluralMetadataModel
{
public PrimaryKey $id;

public string $value;

#[HasOne]
public ?LatinPluralExtraDataModel $extra_data = null;

#[HasOneThrough(through: LatinPluralIntermediateModel::class)]
public ?LatinPluralCriteriaModel $product_criteria = null;
}

#[Table(name: 'extra_data')]
final class LatinPluralExtraDataModel
{
public PrimaryKey $id;

public string $info;
}

#[Table(name: 'intermediate')]
final class LatinPluralIntermediateModel
{
public PrimaryKey $id;

public LatinPluralMetadataModel $metadata;

public string $link;
}

#[Table(name: 'criteria')]
final class LatinPluralCriteriaModel
{
public PrimaryKey $id;

public string $label;
}
Loading