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
12 changes: 12 additions & 0 deletions system/Common.php
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,8 @@ function function_usable(string $functionName): bool
*/
function helper($filenames)
{
static $loaded = [];

$loader = Services::locator(true);

if (! is_array($filenames))
Expand All @@ -659,6 +661,12 @@ function helper($filenames)
$filename .= '_helper';
}

// Check if this helper has already been loaded
if (in_array($filename, $loaded))
{
continue;
}

// If the file is namespaced, we'll just grab that
// file and not search for any others
if (strpos($filename, '\\') !== false)
Expand All @@ -671,6 +679,7 @@ function helper($filenames)
}

$includes[] = $path;
$loaded[] = $filename;
}

// No namespaces, so search in all available locations
Expand All @@ -695,6 +704,7 @@ function helper($filenames)
else
{
$localIncludes[] = $path;
$loaded[] = $filename;
}
}
}
Expand All @@ -704,6 +714,7 @@ function helper($filenames)
{
// @codeCoverageIgnoreStart
$includes[] = $appHelper;
$loaded[] = $filename;
// @codeCoverageIgnoreEnd
}

Expand All @@ -714,6 +725,7 @@ function helper($filenames)
if (! empty($systemHelper))
{
$includes[] = $systemHelper;
$loaded[] = $filename;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion system/Config/BaseService.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public static function locator(bool $getShared = true)
static::$instances['locator'] = new FileLocator(static::autoloader());
}

return static::$instances['locator'];
return static::$mocks['locator'] ?? static::$instances['locator'];
}

return new FileLocator(static::autoloader());
Expand Down
59 changes: 59 additions & 0 deletions tests/_support/Autoloader/FatalLocator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace Tests\Support\Autoloader;

use CodeIgniter\Autoloader\FileLocator;
use RuntimeException;

/**
* Class FatalLocator
*
* A locator replacement designed to throw
* exceptions when used to indicate when
* a lookup actually happens.
*/
class FatalLocator extends FileLocator
{

/**
* Throws.
*
* @param string $file The namespaced file to locate
* @param string $folder The folder within the namespace that we should look for the file.
* @param string $ext The file extension the file should have.
*
* @return string|false The path to the file, or false if not found.
*/
public function locateFile(string $file, string $folder = null, string $ext = 'php')
{
$folder = $folder ?? 'null';
throw new RuntimeException("locateFile({$file}, {$folder}, {$ext})");
}

//--------------------------------------------------------------------

/**
* Searches through all of the defined namespaces looking for a file.
* Returns an array of all found locations for the defined file.
*
* Example:
*
* $locator->search('Config/Routes.php');
* // Assuming PSR4 namespaces include foo and bar, might return:
* [
* 'app/Modules/foo/Config/Routes.php',
* 'app/Modules/bar/Config/Routes.php',
* ]
*
* @param string $path
* @param string $ext
* @param boolean $prioritizeApp
*
* @return array
*/
public function search(string $path, string $ext = 'php', bool $prioritizeApp = true): array
{
$prioritizeApp = $prioritizeApp ? 'true' : 'false';
throw new RuntimeException("search({$path}, {$ext}, {$prioritizeApp})");
}
}
2 changes: 2 additions & 0 deletions tests/_support/Helpers/baguette_helper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?php
// You did it!
46 changes: 46 additions & 0 deletions tests/system/CommonFunctionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use CodeIgniter\Test\TestLogger;
use Config\App;
use Config\Logger;
use Tests\Support\Autoloader\FatalLocator;
use Tests\Support\Models\JobModel;

/**
Expand Down Expand Up @@ -507,4 +508,49 @@ public function dirtyPathsProvider()
],
];
}

//--------------------------------------------------------------------

public function testHelperWithFatalLocatorThrowsException()
{
// Replace the locator with one that will fail if it is called
$locator = new FatalLocator(Services::autoloader());
Services::injectMock('locator', $locator);

try
{
helper('baguette');
$exception = false;
}
catch (\RuntimeException $e)
{
$exception = true;
}

$this->assertTrue($exception);
Services::reset();
}

public function testHelperLoadsOnce()
{
// Load it the first time
helper('baguette');

// Replace the locator with one that will fail if it is called
$locator = new FatalLocator(Services::autoloader());
Services::injectMock('locator', $locator);

try
{
helper('baguette');
$exception = false;
}
catch (\RuntimeException $e)
{
$exception = true;
}

$this->assertFalse($exception);
Services::reset();
}
}