Skip to content

Commit

Permalink
Merge pull request #1592 from hydephp/improved-helper-functions
Browse files Browse the repository at this point in the history
Improved helper functions
  • Loading branch information
caendesilva authored Feb 26, 2024
2 parents de2f20e + ffd7557 commit 34ca9e4
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 0 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This serves two purposes:
### Added
- Added a `@head` stack to the `head.blade.php` component in https://github.com/hydephp/develop/pull/1567
- Added a `Hyde::route()` helper to the `Hyde` facade in https://github.com/hydephp/develop/pull/1591
- Added new global helper functions (`asset()`, `route()`, `url()`) in https://github.com/hydephp/develop/pull/1592

### Changed
- for changes in existing functionality.
Expand Down
76 changes: 76 additions & 0 deletions docs/digging-deeper/helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,82 @@ $time->formatUsingClosure(function (int $minutes, int $seconds): string {
}); // 1 minutes, 30 seconds
```

## Helper Functions

HydePHP comes with a few helper functions to make your life easier.

The most common ones are documented here, however you can also see the full list in the source code [`helpers.php`](https://github.com/hydephp/framework/blob/master/src/helpers.php) file.

### `hyde`

The `hyde` function is a global helper function that returns the HydeKernel instance.
From this, you can access the same methods as you would from the `Hyde` facade.

```php
hyde(); // Returns the HydeKernel instance

hyde()->routes()) === Hyde::routes(); // true
```

It's up to you if you want to use the facade or the global function, or a mix of both.
A benefit of using the global function is that it may have better IDE support.

### `asset`

This is an alias of the `Hyde::asset()` facade method and allows you to get a relative link or URL to an asset in the media directory.

```php
asset('image.png'); // Returns a relative web link to the given image
```

Gets a relative web link to the given image stored in the `_site/media` folder.
If the image is remote (starts with http) it will be returned as is.

If `true` is passed as the second argument, and a base URL is set,
the image will be returned with a qualified absolute URL.

**Example usage:**

```blade
<img src="{{ asset('image.png') }}" alt="My image">
```

### `route`

>info Routing primer: All pages in your Hyde project are automatically tied to an internal route. You can run `php hyde route:list` to see a list of all routes and their route keys.
This is an alias of the `Hyde::route()` facade method and allows you to get a route instance by its route key.

```php
route('index'); // Returns the route instance with the given key
```

If a route does not exist, `null` will be returned. Route instances can be cast to strings to resolve a link to the page.

**Example usage:**

```blade
<a href="{{ route('index') }}">Home</a>
<a href="{{ route('index')->getLink() }}">Home</a>
```

### `url`

This is an alias of the `Hyde::url()` facade method and formats a relative link to an absolute URL using the configured base URL.

```php
url('page.html'); // Returns an absolute URL to the given page
```

[//]: # (If the given link is already an absolute URL, it will be returned as is.)

If a base URL is not set, an exception will be thrown.

**Example usage:**

```blade
<a href="{{ url('page.html') }}">Link</a>
```

## Pagination Utility

Expand Down
34 changes: 34 additions & 0 deletions packages/framework/src/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,40 @@ function unslash(string $string): string
return trim($string, '/\\');
}
}

if (defined('HYDE_COMPATIBILITY_MODE') && HYDE_COMPATIBILITY_MODE === true) {
// Don't declare these functions when running in compatibility mode.
} else {
if (! function_exists('asset')) {
/**
* Get a relative link or URL to an asset in the media directory.
*/
function asset(string $name, bool $preferQualifiedUrl = false): string
{
return hyde()->asset($name, $preferQualifiedUrl);
}
}

if (! function_exists('route')) {
/**
* Get a page route by its key.
*/
function route(string $key): ?Hyde\Support\Models\Route
{
return hyde()->route($key);
}
}

if (! function_exists('url')) {
/**
* Get a qualified URL to the supplied path if a base URL is set.
*/
function url(string $path = ''): string
{
return hyde()->url($path);
}
}
}
}

namespace Hyde {
Expand Down
103 changes: 103 additions & 0 deletions packages/framework/tests/Feature/HelpersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
use Hyde\Hyde;
use Hyde\Testing\TestCase;
use Symfony\Component\Yaml\Yaml;
use Hyde\Support\Facades\Render;
use Hyde\Foundation\Facades\Routes;

/**
* Covers the helpers in helpers.php.
Expand Down Expand Up @@ -64,6 +66,107 @@ public function testUnslashFunctionTrimsTrailingSlashes()
}
}

/** @covers ::asset */
public function testAssetFunction()
{
$this->assertSame(Hyde::asset('foo'), asset('foo'));
$this->assertSame('media/foo', asset('foo'));
}

/** @covers ::asset */
public function testAssetFunctionWithQualifiedUrl()
{
$this->assertSame(Hyde::asset('foo', true), asset('foo', true));
$this->assertSame('http://localhost/media/foo', asset('foo', true));
}

/** @covers ::asset */
public function testAssetFunctionWithExternalUrl()
{
$this->assertSame('https://example.com/foo', asset('https://example.com/foo'));
$this->assertSame('https://example.com/foo', asset('https://example.com/foo', true));
}

/** @covers ::asset */
public function testAssetFunctionWithQualifiedUrlAndNoBaseUrl()
{
$this->app['config']->set(['hyde.url' => null]);
$this->assertSame('media/foo', asset('foo', true));
}

/** @covers ::asset */
public function testAssetFunctionFromNestedPage()
{
Render::shouldReceive('getRouteKey')->andReturn('foo/bar');

$this->assertSame('../media/foo', asset('foo'));
}

/** @covers ::asset */
public function testAssetFunctionFromDeeplyNestedPage()
{
Render::shouldReceive('getRouteKey')->andReturn('foo/bar/baz');

$this->assertSame('../../media/foo', asset('foo'));
}

/** @covers ::asset */
public function testAssetFunctionWithCustomMediaDirectory()
{
Hyde::setMediaDirectory('custom');

$this->assertSame('custom/foo', asset('foo'));
}

/** @covers ::route */
public function testRouteFunction()
{
$this->assertNotNull(Hyde::route('index'));
$this->assertSame(Routes::get('index'), route('index'));
}

/** @covers ::route */
public function testRouteFunctionWithInvalidRoute()
{
$this->assertNull(route('foo'));
}

/** @covers ::route */
public function testRouteFunctionReturnsNullForNonExistentRoute()
{
$this->assertNull(route('nonexistent'));
}

/** @covers ::url */
public function testUrlFunction()
{
$this->assertSame(Hyde::url('foo'), url('foo'));
}

/** @covers ::url */
public function testUrlFunctionWithBaseUrl()
{
$this->app['config']->set(['hyde.url' => 'http://localhost']);
$this->assertSame('http://localhost/foo', url('foo'));
}

/** @covers ::url */
public function testUrlFunctionWithoutBaseUrl()
{
$this->app['config']->set(['hyde.url' => null]);
$this->expectException(\Hyde\Framework\Exceptions\BaseUrlNotSetException::class);
$this->assertNull(url('foo'));
}

/** @covers ::url */
public function testUrlFunctionWithAlreadyQualifiedUrl()
{
$this->markTestSkipped('The url function does not check if the URL is already qualified.');

$this->assertSame('https://example.com/foo', url('https://example.com/foo'));
$this->assertSame('http://localhost/foo', url('http://localhost/foo'));
}

/** @covers ::\Hyde\hyde */
public function testHydeFunctionExistsInHydeNamespace()
{
Expand Down

0 comments on commit 34ca9e4

Please sign in to comment.