-
Notifications
You must be signed in to change notification settings - Fork 184
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #414 from facade/feature/livewire-support
Add better livewire support
- Loading branch information
Showing
21 changed files
with
828 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -70,6 +70,7 @@ const predefinedContextItemGroups = [ | |
'logs', | ||
'dumps', | ||
'exception', | ||
'livewire', | ||
]; | ||
export default { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<template> | ||
<div class="tab-content"> | ||
<div class="layout-col"> | ||
<DefinitionList title="Component" class="tab-content-section"> | ||
<DefinitionListRow | ||
v-for="(value, key) in livewire" | ||
v-if="key.startsWith('component_')" | ||
:key="key" | ||
:label="lookupKey(key)" | ||
>{{ value }}</DefinitionListRow | ||
> | ||
</DefinitionList> | ||
<DefinitionList title="Updates" class="tab-content-section"> | ||
<DefinitionListRow | ||
v-for="(value, key) in livewire.updates" | ||
:key="key" | ||
:label="value['type']" | ||
> | ||
<DefinitionList> | ||
<DefinitionListRow | ||
v-for="(parameter, key) in value['payload'] || []" | ||
:label="key" | ||
:key="key" | ||
> | ||
<code class="code-inline"> | ||
<pre>{{ parameter }}</pre> | ||
</code> | ||
</DefinitionListRow> | ||
</DefinitionList> | ||
</DefinitionListRow> | ||
</DefinitionList> | ||
<DefinitionList title="Data" class="tab-content-section"> | ||
<DefinitionListRow v-for="(value, key) in livewire.data" :key="key" :label="key"> | ||
<template v-if="typeof value === 'string'"> | ||
{{ value }} | ||
</template> | ||
<code v-else class="code-inline"> | ||
<pre>{{ value }}</pre> | ||
</code> | ||
</DefinitionListRow> | ||
</DefinitionList> | ||
</div> | ||
</div> | ||
</template> | ||
<script> | ||
import DefinitionList from '../Shared/DefinitionList'; | ||
import DefinitionListRow from '../Shared/DefinitionListRow.js'; | ||
import upperFirst from 'lodash/upperFirst'; | ||
const predefinedKeys = { | ||
component_alias: 'Alias', | ||
component_id: 'Id', | ||
component_class: 'Class', | ||
}; | ||
export default { | ||
inject: ['report'], | ||
components: { DefinitionListRow, DefinitionList }, | ||
filters: { | ||
upperFirst, | ||
}, | ||
computed: { | ||
livewire() { | ||
return this.report.context.livewire; | ||
}, | ||
data() { | ||
return this.report.context.livewire.data; | ||
}, | ||
updates() { | ||
return this.report.context.livewire.updates; | ||
}, | ||
}, | ||
methods: { | ||
lookupKey(key) { | ||
return predefinedKeys[key] || key; | ||
}, | ||
}, | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
<?php | ||
|
||
namespace Facade\Ignition\Context; | ||
|
||
use Exception; | ||
use Illuminate\Http\Request; | ||
use Illuminate\Support\Arr; | ||
use Livewire\LivewireManager; | ||
|
||
class LivewireRequestContext extends LaravelRequestContext | ||
{ | ||
/** @var \Livewire\LivewireManager */ | ||
protected $livewireManager; | ||
|
||
public function __construct( | ||
Request $request, | ||
LivewireManager $livewireManager | ||
) { | ||
parent::__construct($request); | ||
|
||
$this->livewireManager = $livewireManager; | ||
} | ||
|
||
public function getRequest(): array | ||
{ | ||
$properties = parent::getRequest(); | ||
|
||
$properties['method'] = $this->livewireManager->originalMethod(); | ||
$properties['url'] = $this->livewireManager->originalUrl(); | ||
|
||
return $properties; | ||
} | ||
|
||
public function toArray(): array | ||
{ | ||
$properties = parent::toArray(); | ||
|
||
$properties['livewire'] = $this->getLiveWireInformation(); | ||
|
||
return $properties; | ||
} | ||
|
||
protected function getLiveWireInformation(): array | ||
{ | ||
$componentId = $this->request->input('fingerprint.id'); | ||
$componentAlias = $this->request->input('fingerprint.name'); | ||
|
||
if ($componentAlias === null) { | ||
return []; | ||
} | ||
|
||
try { | ||
$componentClass = $this->livewireManager->getClass($componentAlias); | ||
} catch (Exception $e) { | ||
$componentClass = null; | ||
} | ||
|
||
return [ | ||
'component_class' => $componentClass, | ||
'component_alias' => $componentAlias, | ||
'component_id' => $componentId, | ||
'data' => $this->resolveData(), | ||
'updates' => $this->resolveUpdates(), | ||
]; | ||
} | ||
|
||
protected function resolveData(): array | ||
{ | ||
$data = $this->request->input('serverMemo.data') ?? []; | ||
|
||
$dataMeta = $this->request->input('serverMemo.dataMeta') ?? []; | ||
|
||
foreach ($dataMeta['modelCollections'] ?? [] as $key => $value) { | ||
$data[$key] = array_merge($data[$key] ?? [], $value); | ||
} | ||
|
||
foreach ($dataMeta['models'] ?? [] as $key => $value) { | ||
$data[$key] = array_merge($data[$key] ?? [], $value); | ||
} | ||
|
||
return $data; | ||
} | ||
|
||
protected function resolveUpdates() | ||
{ | ||
$updates = $this->request->input('updates') ?? []; | ||
|
||
return array_map(function (array $update) { | ||
$update['payload'] = Arr::except($update['payload'] ?? [], ['id']); | ||
|
||
return $update; | ||
}, $updates); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
src/SolutionProviders/UndefinedLivewireMethodSolutionProvider.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
|
||
namespace Facade\Ignition\SolutionProviders; | ||
|
||
use Facade\Ignition\Solutions\SuggestLivewireMethodNameSolution; | ||
use Facade\Ignition\Support\LivewireComponentParser; | ||
use Facade\IgnitionContracts\HasSolutionsForThrowable; | ||
use Livewire\Exceptions\MethodNotFoundException; | ||
use Throwable; | ||
|
||
class UndefinedLivewireMethodSolutionProvider implements HasSolutionsForThrowable | ||
{ | ||
public function canSolve(Throwable $throwable): bool | ||
{ | ||
return $throwable instanceof MethodNotFoundException; | ||
} | ||
|
||
public function getSolutions(Throwable $throwable): array | ||
{ | ||
['methodName' => $methodName, 'component' => $component] = $this->getMethodAndComponent($throwable); | ||
|
||
if ($methodName === null || $component === null) { | ||
return []; | ||
} | ||
|
||
$parsed = LivewireComponentParser::create($component); | ||
|
||
return $parsed->getMethodNamesLike($methodName) | ||
->map(function (string $suggested) use ($parsed, $methodName) { | ||
return new SuggestLivewireMethodNameSolution( | ||
$methodName, | ||
$parsed->getComponentClass(), | ||
$suggested | ||
); | ||
}) | ||
->toArray(); | ||
} | ||
|
||
protected function getMethodAndComponent(Throwable $throwable): array | ||
{ | ||
preg_match_all('/\[([\d\w\-_]*)\]/m', $throwable->getMessage(), $matches, PREG_SET_ORDER); | ||
|
||
return [ | ||
'methodName' => $matches[0][1] ?? null, | ||
'component' => $matches[1][1] ?? null, | ||
]; | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
src/SolutionProviders/UndefinedLivewirePropertySolutionProvider.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?php | ||
|
||
namespace Facade\Ignition\SolutionProviders; | ||
|
||
use Facade\Ignition\Solutions\SuggestLivewirePropertyNameSolution; | ||
use Facade\Ignition\Support\LivewireComponentParser; | ||
use Facade\IgnitionContracts\HasSolutionsForThrowable; | ||
use Livewire\Exceptions\PropertyNotFoundException; | ||
use Livewire\Exceptions\PublicPropertyNotFoundException; | ||
use Throwable; | ||
|
||
class UndefinedLivewirePropertySolutionProvider implements HasSolutionsForThrowable | ||
{ | ||
public function canSolve(Throwable $throwable): bool | ||
{ | ||
return $throwable instanceof PropertyNotFoundException || $throwable instanceof PublicPropertyNotFoundException; | ||
} | ||
|
||
public function getSolutions(Throwable $throwable): array | ||
{ | ||
['variable' => $variable, 'component' => $component] = $this->getMethodAndComponent($throwable); | ||
|
||
if ($variable === null || $component === null) { | ||
return []; | ||
} | ||
|
||
$parsed = LivewireComponentParser::create($component); | ||
|
||
return $parsed->getPropertyNamesLike($variable) | ||
->map(function (string $suggested) use ($parsed, $variable) { | ||
return new SuggestLivewirePropertyNameSolution( | ||
$variable, | ||
$parsed->getComponentClass(), | ||
'$'.$suggested | ||
); | ||
}) | ||
->toArray(); | ||
} | ||
|
||
protected function getMethodAndComponent(Throwable $throwable): array | ||
{ | ||
preg_match_all('/\[([\d\w\-_\$]*)\]/m', $throwable->getMessage(), $matches, PREG_SET_ORDER, 0); | ||
|
||
return [ | ||
'variable' => $matches[0][1] ?? null, | ||
'component' => $matches[1][1] ?? null, | ||
]; | ||
} | ||
} |
Oops, something went wrong.