From b0f00bc9d7bbf4d00a3dbd8d91d90e0af06dce15 Mon Sep 17 00:00:00 2001
From: Attila Fulop <1162360+fulopattila122@users.noreply.github.com>
Date: Thu, 9 Jan 2025 14:31:04 +0200
Subject: [PATCH] Added the `url` option to the avatar widget
---
.github/workflows/tests.yml | 2 +-
Changelog.md | 5 +
src/Widgets/Avatar.php | 13 ++-
src/resources/views/widgets/avatar.blade.php | 3 +-
tests/AvatarWidgetTest.php | 110 +++++++++++++++++++
5 files changed, 128 insertions(+), 5 deletions(-)
create mode 100644 tests/AvatarWidgetTest.php
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 94cebab1..5b90d645 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
php: ['8.2', '8.3', '8.4']
- laravel: ['10.0', '10.48', '11.0', '11.36']
+ laravel: ['10.0', '10.48', '11.0', '11.37']
name: PHP ${{ matrix.php }} Laravel ${{ matrix.laravel }}
steps:
- name: Checkout
diff --git a/Changelog.md b/Changelog.md
index c70a0162..e30422d6 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,10 @@
# AppShell Changelog
+## Unreleased
+##### 2025-XX-YY
+
+- Added the `url` option to the avatar widget
+
## 4.6.0
##### 2024-12-19
diff --git a/src/Widgets/Avatar.php b/src/Widgets/Avatar.php
index 9d04c08e..1c889825 100644
--- a/src/Widgets/Avatar.php
+++ b/src/Widgets/Avatar.php
@@ -28,6 +28,9 @@ class Avatar implements Widget
private const DEFAULT_AVATAR_SIZE = 50;
+ /** @var null|callable */
+ private $url;
+
/** @var callable */
private $model;
@@ -36,15 +39,20 @@ class Avatar implements Widget
private ?int $size = null;
- public function __construct(Theme $theme, callable $model)
+ public function __construct(Theme $theme, callable $model, ?callable $url = null)
{
$this->theme = $theme;
$this->model = $model;
+ $this->url = $url;
}
public static function create(Theme $theme, array $options = []): Widget
{
- $instance = new static($theme, self::makeCallable($options['model'] ?? '$model'));
+ $instance = new static(
+ $theme,
+ self::makeCallable($options['model'] ?? '$model'),
+ isset($options['url']) ? self::makeCallable($options['url']) : null,
+ );
$instance->processRenderingConditions($options);
if (isset($options['tooltip'])) {
$instance->tooltip = self::makeCallable($options['tooltip']);
@@ -67,6 +75,7 @@ public function render($data = null): string
'data' => call_user_func($this->model, $data, $this),
'tooltip' => null !== $this->tooltip ? call_user_func($this->tooltip, $data, $this) : null,
'size' => $this->size ?? self::DEFAULT_AVATAR_SIZE,
+ 'url' => null !== $this->url ? call_user_func($this->url, $data, $this) : null,
]);
}
}
diff --git a/src/resources/views/widgets/avatar.blade.php b/src/resources/views/widgets/avatar.blade.php
index 958cdecd..06b214c0 100644
--- a/src/resources/views/widgets/avatar.blade.php
+++ b/src/resources/views/widgets/avatar.blade.php
@@ -1,2 +1 @@
-
-
+@if($url)@endif
@if($url)@endif
diff --git a/tests/AvatarWidgetTest.php b/tests/AvatarWidgetTest.php
new file mode 100644
index 00000000..c96e995e
--- /dev/null
+++ b/tests/AvatarWidgetTest.php
@@ -0,0 +1,110 @@
+ 'test.user.show']);
+ }
+
+ /** @test */
+ public function it_renders_a_default_when_the_model_is_null()
+ {
+ $widget = Avatar::create(new AppShellTheme());
+
+ $html = trim($widget->render());
+ $this->assertStringContainsString('
assertStringContainsString('src="https://www.gravatar.com/avatar/00000000000000000000000000000000', $html);
+ }
+
+ /** @test */
+ public function it_renders_the_md5_of_the_models_email_when_given()
+ {
+ $user = new \stdClass();
+ $user->email = 'test@example.com';
+ $md5 = md5($user->email);
+ $widget = Avatar::create(new AppShellTheme());
+
+ $html = trim($widget->render($user));
+ $this->assertStringContainsString('
assertStringContainsString($md5, $html);
+ }
+
+ /** @test */
+ public function it_substitutes_placeholders_when_given()
+ {
+ $user = new \stdClass();
+ $user->email = 'giovanni.gatto@catsville.com';
+ $md5 = md5($user->email);
+ $order = new \stdClass();
+ $order->user = $user;
+ $widget = Avatar::create(new AppShellTheme(), ['model' => '$model.user']);
+
+ $html = trim($widget->render($order));
+ $this->assertStringContainsString('
assertStringContainsString($md5, $html);
+ }
+
+ /** @test */
+ public function it_does_not_render_a_link_if_such_parameter_was_not_passed()
+ {
+ $user = new \stdClass();
+ $user->email = 'test@example.com';
+ $widget = Avatar::create(new AppShellTheme());
+
+ $html = trim($widget->render($user));
+ $this->assertStringNotContainsString('assertStringNotContainsString('href="', $html);
+ }
+
+ /** @test */
+ public function a_link_can_be_rendered_optionally()
+ {
+ $user = new \stdClass();
+ $user->email = 'giovanni.gatto@catsville.com';
+ $user->id = 35688;
+ $md5 = md5($user->email);
+
+ $widget = Avatar::create(new AppShellTheme(), ['url' => 'https://penny.cz']);
+
+ $html = trim($widget->render($user));
+ $this->assertStringContainsString('
assertStringContainsString($md5, $html);
+ $this->assertStringContainsString('', $html);
+ }
+
+ /** @test */
+ public function a_route_based_link_can_be_rendered_optionally()
+ {
+ $user = new \stdClass();
+ $user->email = 'giovanni.gatto@catsville.com';
+ $user->id = 35688;
+ $md5 = md5($user->email);
+
+ $widget = Avatar::create(new AppShellTheme(), ['url' => ['route' => 'test.user.show', 'parameters' => ['$model.id']]]);
+
+ $html = trim($widget->render($user));
+ $this->assertStringContainsString('
assertStringContainsString($md5, $html);
+ $this->assertStringContainsString('', $html);
+ }
+}