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
3 changes: 2 additions & 1 deletion docs/guide/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ sharp()->context()->breadcrumb();

Get the current or previous breadcrumb item.

### `previousShowSegment(?string $entityKeyOrClassName = null): ?BreadcrumbItem`
### `previousShowSegment(?string $entityKeyOrClassName = null, ?string $subEntity = null): ?BreadcrumbItem`
### `previousListSegment(?string $entityKeyOrClassName = null): ?BreadcrumbItem`

Get (if existing) the closest Show or List in the breadcrumb.
Expand All @@ -87,6 +87,7 @@ A `BreadcrumbItem` instance has the same methods seen above:
#### `isUpdate(): bool`
#### `isCreation(): bool`
#### `instanceId(): string`
#### `entityIs(string $entityKeyOrClassName, ?string $subEntity = null): bool`

Here's an example of how this information could be useful: imagine you have a Show for a `Post` instance, with an Embedded Entity List of `Comment`. When creating a new `Comment`, you'll need to set its `post_id` attribute on the Form `update()` method. You can for this make use of the breadcrumb context like this:

Expand Down
12 changes: 5 additions & 7 deletions src/Http/Context/SharpBreadcrumb.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ public function previousSegment(): ?BreadcrumbItem
return $this->breadcrumbItems()->reverse()->skip(1)->first();
}

public function previousShowSegment(?string $entityKeyOrClassName = null): ?BreadcrumbItem
public function previousShowSegment(?string $entityKeyOrClassName = null, ?string $subEntity = null): ?BreadcrumbItem
{
return $this->findPreviousSegment('s-show', $entityKeyOrClassName);
return $this->findPreviousSegment('s-show', $entityKeyOrClassName, $subEntity);
}

public function previousListSegment(?string $entityKeyOrClassName = null): ?BreadcrumbItem
Expand Down Expand Up @@ -111,7 +111,7 @@ public function breadcrumbItems(): Collection
return $this->breadcrumbItems;
}

private function findPreviousSegment(string $type, ?string $entityKeyOrClassName = null): ?BreadcrumbItem
private function findPreviousSegment(string $type, ?string $entityKeyOrClassName = null, ?string $subEntity = null): ?BreadcrumbItem
{
$modeNotEquals = false;
if ($entityKeyOrClassName && Str::startsWith($entityKeyOrClassName, '!')) {
Expand All @@ -124,10 +124,8 @@ private function findPreviousSegment(string $type, ?string $entityKeyOrClassName
->filter(fn (BreadcrumbItem $item) => $item->type === $type)
->when($entityKeyOrClassName !== null, fn ($items) => $items
->filter(fn (BreadcrumbItem $breadcrumbItem) => $modeNotEquals
? $breadcrumbItem->entityKey() !== app(SharpEntityManager::class)
->entityKeyFor($entityKeyOrClassName)
: $breadcrumbItem->entityKey() === app(SharpEntityManager::class)
->entityKeyFor($entityKeyOrClassName)
? ! $breadcrumbItem->entityIs($entityKeyOrClassName, $subEntity)
: $breadcrumbItem->entityIs($entityKeyOrClassName, $subEntity)
)
)
->first();
Expand Down
10 changes: 10 additions & 0 deletions src/Http/Context/Util/BreadcrumbItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Code16\Sharp\Http\Context\Util;

use Code16\Sharp\Utils\Entities\SharpEntityManager;
use Code16\Sharp\Utils\Entities\ValueObjects\EntityKey;

class BreadcrumbItem
{
Expand Down Expand Up @@ -67,6 +68,15 @@ public function is(BreadcrumbItem $item): bool
&& $this->instance === $item->instance;
}

public function entityIs(string $entityKeyOrClassName, ?string $subEntity = null): bool
{
$selfKey = new EntityKey($this->key);
$resolvedEntityKey = app(SharpEntityManager::class)->entityKeyFor($entityKeyOrClassName);

return $selfKey->baseKey() === $resolvedEntityKey
&& (! $subEntity || $selfKey->subEntity() === $subEntity);
}

public function entityKey(): string
{
return $this->key;
Expand Down
62 changes: 61 additions & 1 deletion tests/Http/Context/SharpContextTest.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
<?php

use Code16\Sharp\Config\SharpConfigBuilder;
use Code16\Sharp\EntityList\Filters\EntityListSelectFilter;
use Code16\Sharp\Tests\Fixtures\Entities\PersonEntity;
use Code16\Sharp\Tests\Fixtures\Entities\SinglePersonEntity;
use Code16\Sharp\Tests\Fixtures\Sharp\PersonForm;
use Code16\Sharp\Tests\Fixtures\Sharp\PersonList;
use Code16\Sharp\Tests\Unit\Utils\FakesBreadcrumb;
use Code16\Sharp\Utils\Entities\SharpEntity;
use Code16\Sharp\Utils\Entities\SharpEntityManager;

uses(FakesBreadcrumb::class);

Expand Down Expand Up @@ -85,7 +89,7 @@
});

it('allows to get previous show of a given entity class name from request', function () {
app(\Code16\Sharp\Config\SharpConfigBuilder::class)->declareEntity(PersonEntity::class);
app(SharpConfigBuilder::class)->declareEntity(PersonEntity::class);
$this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/31/s-show/person/42/s-show/child/84/s-form/child/84');

expect(sharp()->context()->breadcrumb())
Expand All @@ -95,6 +99,62 @@
->previousShowSegment(PersonEntity::class)->instanceId()->toEqual(42);
});

it('allows to get previous show of a given entity class name & subentity from request', function () {
app(SharpConfigBuilder::class)->declareEntity(PersonEntity::class);
app(SharpEntityManager::class)->entityFor('person')->setMultiforms([
'multiform' => [PersonForm::class, 'Multiform'],
]);
$this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/31/s-show/person:multiform/42/s-show/child:multiform/84/s-form/child/84');

expect(sharp()->context()->breadcrumb())
->previousShowSegment()->entityKey()->toBe('child:multiform')
->previousShowSegment()->instanceId()->toEqual(84)
->previousShowSegment(PersonEntity::class)->entityKey()->toBe('person:multiform')
->previousShowSegment(PersonEntity::class)->instanceId()->toEqual(42)
->previousShowSegment(PersonEntity::class, 'multiform')->entityKey()->toBe('person:multiform')
->previousShowSegment(PersonEntity::class, 'multiform')->instanceId()->toEqual(42);
});

it('allows to check entity of a segment', function () {
app(SharpConfigBuilder::class)->declareEntity(PersonEntity::class);
app(SharpConfigBuilder::class)->declareEntity(SinglePersonEntity::class);
$this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/1/s-form/person/1');

expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs(PersonEntity::class))->toBeTrue();
expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs('person'))->toBeTrue();
expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs(PersonEntity::class, 'multiform'))->toBeFalse();
expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs(SinglePersonEntity::class))->toBeFalse();
expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs('child'))->toBeFalse();
expect(sharp()->context()->breadcrumb()->previousShowSegment()->entityIs(PersonEntity::class))->toBeTrue();
expect(sharp()->context()->breadcrumb()->previousShowSegment()->entityIs(PersonEntity::class, 'multiform'))->toBeFalse();
expect(sharp()->context()->breadcrumb()->previousShowSegment()->entityIs(SinglePersonEntity::class))->toBeFalse();
expect(sharp()->context()->breadcrumb()->previousShowSegment()->entityIs('child'))->toBeFalse();
});

it('allows to check entity with subentity of a segment', function () {
app(SharpConfigBuilder::class)->declareEntity(PersonEntity::class);
app(SharpConfigBuilder::class)->declareEntity(SinglePersonEntity::class);
app(SharpEntityManager::class)->entityFor('person')->setMultiforms([
'multiform' => [PersonForm::class, 'Multiform'],
]);
$this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person:multiform/1/s-form/person:multiform/1');

expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs(PersonEntity::class))->toBeTrue();
expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs('person'))->toBeTrue();
expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs('person', 'multiform'))->toBeTrue();
expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs(PersonEntity::class, 'multiform'))->toBeTrue();
expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs(PersonEntity::class, 'other-multiform'))->toBeFalse();
expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs(SinglePersonEntity::class))->toBeFalse();
expect(sharp()->context()->breadcrumb()->currentSegment()->entityIs('child'))->toBeFalse();
expect(sharp()->context()->breadcrumb()->previousShowSegment()->entityIs(PersonEntity::class))->toBeTrue();
expect(sharp()->context()->breadcrumb()->previousShowSegment()->entityIs('person'))->toBeTrue();
expect(sharp()->context()->breadcrumb()->previousShowSegment()->entityIs('person', 'multiform'))->toBeTrue();
expect(sharp()->context()->breadcrumb()->previousShowSegment()->entityIs(PersonEntity::class, 'multiform'))->toBeTrue();
expect(sharp()->context()->breadcrumb()->previousShowSegment()->entityIs(PersonEntity::class, 'other-multiform'))->toBeFalse();
expect(sharp()->context()->breadcrumb()->previousShowSegment()->entityIs(SinglePersonEntity::class))->toBeFalse();
expect(sharp()->context()->breadcrumb()->previousShowSegment()->entityIs('child'))->toBeFalse();
});

it('allows to get previous url from request', function () {
$this->fakeBreadcrumbWithUrl('/sharp/s-list/person/s-show/person/42/s-form/child/2');

Expand Down
Loading