Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/Phaseolies/Helpers/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use Phaseolies\Utilities\Paginator;
use Phaseolies\Translation\Translator;
use Phaseolies\Support\UrlGenerator;
use Phaseolies\Support\Contracts\UrlGeneratorInterface;
use Phaseolies\Support\StringService;
use Phaseolies\Support\Facades\Log;
use Phaseolies\Support\Facades\Crypt;
Expand Down Expand Up @@ -194,11 +194,11 @@ function lang(): Translator
* @param string|null $path
* @param mixed $parameters
* @param bool|null $secure
* @return ($path is null ? \Phaseolies\Support\UrlGenerator : string)
* @return ($path is null ? \Phaseolies\Support\Contracts\UrlGeneratorInterface : string)
*/
function url(?string $path = null, $parameters = [], ?bool $secure = null)
{
$urlGenerator = app(UrlGenerator::class);
$urlGenerator = app(UrlGeneratorInterface::class);

if (is_null($path)) {
return $urlGenerator;
Expand Down
6 changes: 3 additions & 3 deletions src/Phaseolies/Support/Contracts/UrlGeneratorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface UrlGeneratorInterface
public function enqueue(string $path = '/', ?bool $secure = null): string;

/**
* Generate the current full URL without query parameters.
* Generate the current full URL, including query parameters.
*
* @return string
*/
Expand Down Expand Up @@ -92,10 +92,10 @@ public function signed(string $path = '/', array|string|int $parameters = [], in
/**
* Determine whether a value is a valid URL.
*
* @param string $path
* @param mixed $path
* @return bool
*/
public function isValid(string $path): bool;
public function isValid(mixed $path): bool;

/**
* Get the configured base URL.
Expand Down
16 changes: 8 additions & 8 deletions src/Phaseolies/Support/Facades/URL.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@
use Phaseolies\Facade\BaseFacade;

/**
* @method static string enqueue(string $path = '/', $secure = null)
* @method static string enqueue(string $path = '/', ?bool $secure = null)
* @method static string full()
* @method static string current()
* @method static string route(string $name, array|string|int $parameters = [], ?bool $secure = null)
* @method static \Phaseolies\Support\UrlGenerator to($path = '/')
* @method static \Phaseolies\Support\UrlGenerator withQuery(array|string $query = [])
* @method static \Phaseolies\Support\UrlGenerator withSignature($expiration = 3600)
* @method static \Phaseolies\Support\UrlGenerator withFragment($fragment = '')
* @method static \Phaseolies\Support\Contracts\UrlGeneratorInterface to(string $path = '/', array|string|int $parameters = [], ?bool $secure = null)
* @method static \Phaseolies\Support\Contracts\UrlGeneratorInterface withQuery(array|string $query = [])
* @method static \Phaseolies\Support\Contracts\UrlGeneratorInterface withSignature(int $expiration = 3600)
* @method static \Phaseolies\Support\Contracts\UrlGeneratorInterface withFragment(string $fragment = '')
* @method static string make()
* @method static string signed(string $path = '/', array|string|int $parameters = [], int $expiration = 3600, ?bool $secure = null)
* @method static bool isValid(string $url)
* @method static bool isValid(mixed $url)
* @method static string base()
* @method static \Phaseolies\Support\UrlGenerator setSecure(bool $secure)
* @method static \Phaseolies\Support\Contracts\UrlGeneratorInterface setSecure(bool $secure)
*
* @see \Phaseolies\Support\UrlGenerator
* @see \Phaseolies\Support\Contracts\UrlGeneratorInterface
*/
class URL extends BaseFacade
{
Expand Down
25 changes: 22 additions & 3 deletions src/Phaseolies/Support/UrlGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public function enqueue(string $path = '/', ?bool $secure = null): string
}

/**
* Generate a full URL without query parameters.
* Generate the current full URL, including query parameters.
*
* @return string
*/
Expand Down Expand Up @@ -242,9 +242,24 @@ public function make(): string
$url .= '#' . $this->fragment;
}

$this->resetBuilderState();

return $url;
}

/**
* Reset the per-URL builder state
*
* @return void
*/
protected function resetBuilderState(): void
{
$this->path = '/';
$this->query = [];
$this->fragment = '';
$this->expiration = 0;
}

/**
* Generate a signed URL.
*
Expand Down Expand Up @@ -282,11 +297,15 @@ protected function createSignature(array $parameters): string
* This method is taken from PHP Laravel framework
* Determine if the given path is a valid URL.
*
* @param string $path
* @param mixed $path
* @return bool
*/
public function isValid(string $path): bool
public function isValid(mixed $path): bool
{
if (! is_string($path)) {
return false;
}

if (! preg_match('~^(#|//|https?://|(mailto|tel|sms):)~', $path)) {
return filter_var($path, FILTER_VALIDATE_URL) !== false;
}
Expand Down
31 changes: 31 additions & 0 deletions tests/UrlGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,37 @@ public function testApplicationBindsTheUrlContractAndLegacyServiceNameToTheSameS
}
}

public function testIsValidReturnsFalseForNonStringValues(): void
{
$this->assertFalse($this->urlGenerator->isValid(null));
$this->assertFalse($this->urlGenerator->isValid(123));
$this->assertFalse($this->urlGenerator->isValid(['https://example.com']));
}

public function testBuilderStateDoesNotLeakBetweenUrls(): void
{
$this->urlGenerator->to('first')->withQuery(['id' => 1])->withFragment('top')->make();

$this->assertEquals('http://localhost/second', $this->urlGenerator->to('second')->make());
}

public function testUrlHelperResolvesTheSharedSingleton(): void
{
$app = $this->getMockBuilder(Application::class)->disableOriginalConstructor()->onlyMethods([])->getMock();
(new ReflectionClass(Container::class))->getConstructor()->invoke($app);
$previous = Container::getInstance();
Container::setInstance($app);

try {
putenv('APP_URL=http://localhost');
(new FacadeLauncher($app))->register();

$this->assertSame($app->get('url'), url());
} finally {
Container::setInstance($previous);
}
}

protected function tearDown(): void
{
unset($_SERVER['HTTP_HOST']);
Expand Down
Loading