Skip to content

Commit

Permalink
Add function that can traverse functions for data_get
Browse files Browse the repository at this point in the history
  • Loading branch information
indykoning committed Dec 19, 2023
1 parent 49a427a commit 2fb1969
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 0 deletions.
36 changes: 36 additions & 0 deletions .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: phpunit

on:
push:
pull_request:
schedule:
- cron: '0 0 * * *'

jobs:
phpunit:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: [8.1, 8.2]
stability: [prefer-lowest, prefer-stable]

name: P${{ matrix.php }}

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick
coverage: none

- name: Install dependencies
run: |
composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-suggest
- name: Execute tests
run: vendor/bin/phpunit
6 changes: 6 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@
"php": "^8.0|^8.1|^8.2",
"illuminate/support": "^9.0|^10.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5.10"
},
"autoload": {
"files": [
"src/helpers.php"
],
"psr-4": {
"Rapidez\\BladeDirectives\\": "src"
}
Expand Down
12 changes: 12 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./src/Tests/Unit</directory>
</testsuite>
</testsuites>
</phpunit>
4 changes: 4 additions & 0 deletions src/BladeDirectivesServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ public function register()
<?php \$attributes ??= new \\Illuminate\\View\\ComponentAttributeBag; ?>
<?php \$attributes = \$attributes->exceptProps($expression); ?>";
});

Blade::if('safeIsset', function ($target, $key = null) {
return boolval(data_get_value($target, $key, false));
});
}

public function boot()
Expand Down
129 changes: 129 additions & 0 deletions src/Tests/Unit/DataGetValueTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?php

namespace Rapidez\BladeDirectives\Tests\Unit;

use PHPUnit\Framework\TestCase;

class TestClass {
function __construct(private $_value)
{}

function value() {
return $this->_value;
}
}

class DataGetValueTest extends TestCase
{
public function test_that_plain_array_returns_value()
{
$target = [
'foo' => [
'bar' => [
'baz' => 'quux'
]
],
];

$this->assertEquals('quux', data_get_value($target, 'foo.bar.baz'));
}

public function test_that_array_with_final_value_function_returns_value()
{
$target = [
'foo' => [
'bar' => [
'baz' => [
'value' => fn() => 'quux'
]
]
],
];

$this->assertEquals('quux', data_get_value($target, 'foo.bar.baz.value'));
}

public function test_that_array_with_value_function_halfway_returns_value()
{
$target = [
'foo' => [
'bar' => [
'value' => fn() => [
'baz' =>'quux'
]
]
],
];

$this->assertEquals('quux', data_get_value($target, 'foo.bar.value.baz'));
}

public function test_that_plain_stdclass_returns_value()
{
$target = (object) [
'foo' => [
'bar' => [
'baz' => 'quux'
]
],
];

$this->assertEquals('quux', data_get_value($target, 'foo.bar.baz'));
}

public function test_that_stdclass_with_final_value_function_returns_value()
{
$target = (object) [
'foo' => [
'bar' => [
'baz' => [
'value' => fn() => 'quux'
]
]
],
];

$this->assertEquals('quux', data_get_value($target, 'foo.bar.baz.value'));
}

public function test_that_stdclass_with_value_function_halfway_returns_value()
{
$target = (object) [
'foo' => [
'bar' => [
'value' => fn() => [
'baz' =>'quux'
]
]
],
];

$this->assertEquals('quux', data_get_value($target, 'foo.bar.value.baz'));
}

public function test_that_class_with_final_value_function_returns_value()
{
$target = (object) [
'foo' => [
'bar' => [
'baz' => new TestClass('quux')
]
],
];

$this->assertEquals('quux', data_get_value($target, 'foo.bar.baz.value'));
}

public function test_that_class_with_value_function_halfway_returns_value()
{
$target = (object) [
'foo' => [
'bar' => new TestClass([
'baz' =>'quux'
])
],
];

$this->assertEquals('quux', data_get_value($target, 'foo.bar.value.baz'));
}
}
61 changes: 61 additions & 0 deletions src/helpers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

use Illuminate\Support\Arr;
use Illuminate\Support\Collection;

if (! function_exists('data_get_value')) {
/**
* Get an item from an array or object using "dot" notation.
* Executing functions along the way as well.
*
* @see https://github.com/laravel/framework/blob/78fa6f2c758e929233889103e2f709d0017c7598/src/Illuminate/Collections/helpers.php#L46
* @param mixed $target
* @param string|array|int|null $key
* @param mixed $default
* @return mixed
*/
function data_get_value($target, $key, $default = null)
{
if (is_null($key)) {
return $target;
}

$key = is_array($key) ? $key : explode('.', $key);

foreach ($key as $i => $segment) {
unset($key[$i]);

if (is_null($segment)) {
return $target;
}

if ($segment === '*') {
if ($target instanceof Collection) {
$target = $target->all();
} elseif (! is_iterable($target)) {
return value($default);
}

$result = [];

foreach ($target as $item) {
$result[] = data_get_value($item, $key);
}

return in_array('*', $key) ? Arr::collapse($result) : $result;
}

if (Arr::accessible($target) && Arr::exists($target, $segment)) {
$target = value($target[$segment]); // Result is wrapped in the value function
} elseif (is_object($target) && isset($target->{$segment})) {
$target = value($target->{$segment}); // Result is wrapped in the value function
} elseif (is_object($target) && method_exists($target, $segment)) {
$target = value($target->{$segment}()); // Added to execute methods if necessary
} else {
return value($default);
}
}

return $target;
}
}

0 comments on commit 2fb1969

Please sign in to comment.