1
0
Fork 0
mirror of https://github.com/archtechx/livewire-access.git synced 2025-12-12 12:24:03 +00:00
This commit is contained in:
Samuel Štancl 2021-03-17 17:28:17 +01:00
parent a29235253b
commit e50e22434f
12 changed files with 159 additions and 138 deletions

View file

@ -3,7 +3,6 @@ name: CI
env:
COMPOSE_INTERACTIVE_NO_CLI: 1
PHP_CS_FIXER_IGNORE_ENV: 1
MYSQL_PORT: 3307
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
on:
@ -18,17 +17,11 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Start docker containers
run: docker-compose up -d
- name: Install composer dependencies
run: composer install
- name: Run tests
run: vendor/bin/phpunit
psalm:
name: Static analysis (Psalm)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install composer dependencies
@ -36,17 +29,6 @@ jobs:
- name: Run psalm
run: vendor/bin/psalm
phpstan:
name: Static analysis (PHPStan)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install composer dependencies
run: composer install
- name: Run phpstan
run: vendor/bin/phpstan analyse
php-cs-fixer:
name: Code style (php-cs-fixer)
runs-on: ubuntu-latest

View file

@ -1,17 +1,50 @@
# Package
# Livewire Access
This package adds PHP 8.0 attribute support to Livewire. In specific, the attributes are used for flagging component properties and methods as *frontend-accessible*.
Components which implement the trait provided by this package will implicitly deny access to all properties and methods if they don't have the `#[FrontendAccess]` attribute, regardless of their visibility.
## Installation
```sh
composer require stancl/package
composer require leanadmin/livewire-access
```
## Usage
```php
// ...
use Livewire\Component;
use Lean\LivewireAccess\WithExplicitAccess;
use Lean\LivewireAccess\FrontendAccess;
class MyComponent extends Component
{
// Use the trait on your component to enable this functionality
use WithExplicitAccess;
// Accessing this from the frontend will throw an exception
public string $inaccessible;
#[FrontendAccess]
public string $accessible; // This property allows frontend access
public function secretMethod()
{
// Calling this from the frontend will throw an exception
}
#[FrontendAccess]
public function secretMethod()
{
// This method allows frontend access
}
}
```
The properties still need to be `public` to be accessible.
The thrown exceptions are identical to those that Livewire would throw if the properties/methods were not public.
## Development
Running all checks locally:
@ -23,8 +56,6 @@ Running all checks locally:
Running tests:
```sh
MYSQL_PORT=3307 docker-compose up -d
phpunit
```

16
check
View file

@ -36,22 +36,6 @@ else
esac
fi
if (./vendor/bin/psalm > /dev/null 2>/dev/null); then
echo '✅ Psalm OK'
else
echo '❌ Psalm FAIL'
offer_run './vendor/bin/psalm'
fi
if (./vendor/bin/phpstan analyse > /dev/null 2>/dev/null); then
echo '✅ PHPStan OK'
else
echo '❌ PHPStan FAIL'
offer_run './vendor/bin/phpstan analyse'
fi
(MYSQL_PORT=3307 docker-compose up -d > /dev/null 2>/dev/null) || true
if (./vendor/bin/phpunit > /dev/null 2>/dev/null); then
echo '✅ PHPUnit OK'
else

View file

@ -1,5 +1,5 @@
{
"name": "stancl/package",
"name": "leanadmin/livewire-access",
"description": "",
"type": "library",
"license": "MIT",
@ -11,27 +11,19 @@
],
"autoload": {
"psr-4": {
"Stancl\\Package\\": "src/"
"Lean\\LivewireAccess\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Stancl\\Package\\Tests\\": "tests/"
"Lean\\LivewireAccess\\Tests\\": "tests/"
}
},
"require": {
"illuminate/support": "^8.24"
"php": "^8.0",
"livewire/livewire": "^2.4"
},
"require-dev": {
"orchestra/testbench": "^6.9",
"vimeo/psalm": "^4.2",
"nunomaduro/larastan": "^0.6.10"
},
"extra": {
"laravel": {
"providers": [
"Stancl\\Package\\PackageServiceProvider"
]
}
"orchestra/testbench": "^6.9"
}
}

View file

@ -1,12 +0,0 @@
version: '3'
services:
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: main
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_TCP_PORT: ${MYSQL_PORT}
ports:
- "${MYSQL_PORT}:${MYSQL_PORT}"

View file

@ -1,25 +0,0 @@
includes:
- ./vendor/nunomaduro/larastan/extension.neon
parameters:
paths:
- src
- tests
level: 8
universalObjectCratesClasses:
- Illuminate\Routing\Route
ignoreErrors:
# -
# message: '#Offset (.*?) does not exist on array\|null#'
# paths:
# - tests/*
# -
# message: '#expects resource, resource\|false given#'
# paths:
# - tests/*
# - '#should return \$this#'
checkMissingIterableValueType: false

12
src/FrontendAccess.php Normal file
View file

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Lean\LivewireAccess;
use Attribute;
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_METHOD)]
class FrontendAccess
{
}

View file

@ -1,32 +0,0 @@
<?php
declare(strict_types=1);
namespace Stancl\Package;
use Illuminate\Support\ServiceProvider;
class PackageServiceProvider extends ServiceProvider
{
public function register(): void
{
}
public function boot(): void
{
// $this->loadViewsFrom(__DIR__ . '/../assets/views', 'package');
// $this->publishes([
// __DIR__ . '/../assets/views' => resource_path('views/vendor/package'),
// ], 'package-views');
// $this->mergeConfigFrom(
// __DIR__ . '/../assets/package.php',
// 'package'
// );
// $this->publishes([
// __DIR__ . '/../assets/package.php' => config_path('package.php'),
// ], 'package-config');
}
}

View file

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace Lean\LivewireAccess;
use ReflectionMethod;
use ReflectionProperty;
trait WithExplicitAccess
{
protected function methodIsPublicAndNotDefinedOnBaseClass($methodName)
{
return parent::methodIsPublicAndNotDefinedOnBaseClass($methodName)
&& count((new ReflectionMethod($this, $methodName))->getAttributes(FrontendAccess::class)) > 0;
}
public function propertyIsPublicAndNotDefinedOnBaseClass($propertyName)
{
return parent::propertyIsPublicAndNotDefinedOnBaseClass($propertyName)
&& count((new ReflectionProperty($this, $propertyName))->getAttributes(FrontendAccess::class)) > 0;
}
}

View file

@ -0,0 +1,55 @@
<?php
namespace Lean\LivewireAccess\Tests;
use Livewire\Exceptions\NonPublicComponentMethodCall;
use Livewire\Exceptions\PublicPropertyNotFoundException;
use Livewire\Livewire;
use Livewire\LivewireServiceProvider;
use Orchestra\Testbench\TestCase as TestbenchTestCase;
class LivewireAccessTest extends TestbenchTestCase
{
protected function getPackageProviders($app)
{
return [
LivewireServiceProvider::class,
];
}
/** @test */
public function public_properties_are_not_accessible_by_default()
{
$this->expectException(PublicPropertyNotFoundException::class);
Livewire::test(TestComponent::class)
->call('$set', 'foo', 'xxx');
}
/** @test */
public function public_properties_can_be_explicitly_accessible()
{
Livewire::test(TestComponent::class)
->call('$set', 'bar', 'xxx');
// No exception
}
/** @test */
public function public_methods_are_not_acccessible_by_default()
{
$this->expectException(NonPublicComponentMethodCall::class);
Livewire::test(TestComponent::class)
->call('abc');
}
/** @test */
public function public_methods_can_be_explicitly_accessible()
{
Livewire::test(TestComponent::class)
->call('def');
// No exception
}
}

View file

@ -1,16 +0,0 @@
<?php
namespace Stancl\Package\Tests;
use Orchestra\Testbench\TestCase as TestbenchTestCase;
use Stancl\Package\PackageServiceProvider;
class TestCase extends TestbenchTestCase
{
protected function getPackageProviders($app)
{
return [
PackageServiceProvider::class,
];
}
}

27
tests/TestComponent.php Normal file
View file

@ -0,0 +1,27 @@
<?php
namespace Lean\LivewireAccess\Tests;
use Lean\LivewireAccess\WithExplicitAccess;
use Lean\LivewireAccess\FrontendAccess;
use Livewire\Component;
class TestComponent extends Component
{
use WithExplicitAccess;
public string $foo = 'foo';
#[FrontendAccess]
public string $bar = 'bar';
public function abc() {}
#[FrontendAccess]
public function def() {}
public function render()
{
return '';
}
}