diff --git a/system/Autoloader/FileLocator.php b/system/Autoloader/FileLocator.php index 4849b295e7..1a301aa035 100644 --- a/system/Autoloader/FileLocator.php +++ b/system/Autoloader/FileLocator.php @@ -151,6 +151,56 @@ class FileLocator //-------------------------------------------------------------------- + /** + * Examines a file and returns the fully qualified domain name. + * + * @param string $file + * + * @return string + */ + public function getClassname(string $file) : string + { + $php = file_get_contents($file); + $tokens = token_get_all($php); + $count = count($tokens); + $dlm = false; + $namespace = ''; + $class_name = ''; + + for ($i = 2; $i < $count; $i++) + { + if ((isset($tokens[$i-2][1]) && ($tokens[$i-2][1] == "phpnamespace" || $tokens[$i-2][1] == "namespace")) || ($dlm && $tokens[$i-1][0] == T_NS_SEPARATOR && $tokens[$i][0] == T_STRING)) + { + if (! $dlm) + { + $namespace = 0; + } + if (isset($tokens[$i][1])) + { + $namespace = $namespace ? $namespace."\\".$tokens[$i][1] : $tokens[$i][1]; + $dlm = true; + } + } + elseif ($dlm && ($tokens[$i][0] != T_NS_SEPARATOR) && ($tokens[$i][0] != T_STRING)) + { + $dlm = false; + } + if (($tokens[$i-2][0] == T_CLASS || (isset($tokens[$i-2][1]) && $tokens[$i-2][1] == "phpclass")) + && $tokens[$i-1][0] == T_WHITESPACE + && $tokens[$i][0] == T_STRING) + { + $class_name = $tokens[$i][1]; + break; + } + } + + if( empty( $class_name ) ) return ""; + + return $namespace .'\\'. $class_name; + } + + //-------------------------------------------------------------------- + /** * Searches through all of the defined namespaces looking for a file. * Returns an array of all found locations for the defined file. diff --git a/system/Common.php b/system/Common.php index 6fceec13f4..72cbe76ed9 100644 --- a/system/Common.php +++ b/system/Common.php @@ -85,6 +85,24 @@ if ( ! function_exists('cache')) //-------------------------------------------------------------------- +if ( ! function_exists('config')) +{ + /** + * More simple way of getting config instances + * + * @param string $name + * @param bool $getShared + * + * @return mixed + */ + function config(string $name, bool $getShared = true) + { + return \CodeIgniter\Config\Config::get($name, $getShared); + } +} + +//-------------------------------------------------------------------- + if ( ! function_exists('view')) { diff --git a/system/Config/BaseService.php b/system/Config/BaseService.php index 1fa59aaa83..b8ffa3b27c 100644 --- a/system/Config/BaseService.php +++ b/system/Config/BaseService.php @@ -36,6 +36,8 @@ * @filesource */ +use CodeIgniter\Autoloader\FileLocator; + /** * Services Configuration file. * @@ -191,7 +193,7 @@ class BaseService // Get instances of all service classes and cache them locally. foreach ($files as $file) { - $classname = static::getClassName($file); + $classname = $locator->getClassname($file); if (! in_array($classname, ['Config\\Services', 'CodeIgniter\\Config\\Services'])) { @@ -214,50 +216,4 @@ class BaseService } } } - - /** - * Examines a file and returns the fully qualified domain name. - * - * @param string $file - * - * @return string - */ - private static function getClassname(string $file) - { - $php = file_get_contents($file); - $tokens = token_get_all($php); - $count = count($tokens); - $dlm = false; - $namespace = ''; - $class_name = ''; - - for ($i = 2; $i < $count; $i++) - { - if ((isset($tokens[$i-2][1]) && ($tokens[$i-2][1] == "phpnamespace" || $tokens[$i-2][1] == "namespace")) || ($dlm && $tokens[$i-1][0] == T_NS_SEPARATOR && $tokens[$i][0] == T_STRING)) - { - if (! $dlm) - { - $namespace = 0; - } - if (isset($tokens[$i][1])) - { - $namespace = $namespace ? $namespace."\\".$tokens[$i][1] : $tokens[$i][1]; - $dlm = true; - } - } - elseif ($dlm && ($tokens[$i][0] != T_NS_SEPARATOR) && ($tokens[$i][0] != T_STRING)) - { - $dlm = false; - } - if (($tokens[$i-2][0] == T_CLASS || (isset($tokens[$i-2][1]) && $tokens[$i-2][1] == "phpclass")) - && $tokens[$i-1][0] == T_WHITESPACE - && $tokens[$i][0] == T_STRING) - { - $class_name = $tokens[$i][1]; - break; - } - } - - return $namespace .'\\'. $class_name; - } } diff --git a/system/Config/Config.php b/system/Config/Config.php new file mode 100644 index 0000000000..0cf79dd3e7 --- /dev/null +++ b/system/Config/Config.php @@ -0,0 +1,122 @@ +locateFile($name, 'Config'); + + if (empty($file)) + { + return null; + } + + $name = $locator->getClassname($file); + + if (empty($name)) + { + return null; + } + + return new $name(); + } + + //-------------------------------------------------------------------- +} diff --git a/system/Helpers/filesystem_helper.php b/system/Helpers/filesystem_helper.php index 7e7782386c..f947305a10 100644 --- a/system/Helpers/filesystem_helper.php +++ b/system/Helpers/filesystem_helper.php @@ -1,4 +1,5 @@ 0) ? @rmdir($path) : true; + } + catch (\Exception $fe) { return false; } - - while (false !== ($filename = @readdir($current_dir))) - { - if ($filename !== '.' && $filename !== '..') - { - if (is_dir($path . DIRECTORY_SEPARATOR . $filename) && $filename[0] !== '.') - { - delete_files($path . DIRECTORY_SEPARATOR . $filename, $delDir, $htdocs, $_level + 1); - } - elseif ($htdocs !== true || ! preg_match('/^(\.htaccess|index\.(html|htm|php)|web\.config)$/i', $filename)) - { - @unlink($path . DIRECTORY_SEPARATOR . $filename); - } - } - } - - closedir($current_dir); - - return ($delDir === true && $_level > 0) ? @rmdir($path) : true; } } @@ -216,8 +228,9 @@ if ( ! function_exists('get_filenames')) { static $filedata = []; - if ($fp = @opendir($source_dir)) + try { + $fp = opendir($source_dir); // reset the array and make sure $source_dir has a trailing slash on the initial call if ($recursion === false) { @@ -240,8 +253,10 @@ if ( ! function_exists('get_filenames')) closedir($fp); return $filedata; } - - return []; + catch (\Exception $fe) + { + return []; + } } } @@ -270,34 +285,38 @@ if ( ! function_exists('get_dir_file_info')) static $filedata = []; $relative_path = $source_dir; - if ($fp = @opendir($source_dir)) + try { - // reset the array and make sure $source_dir has a trailing slash on the initial call - if ($recursion === false) - { - $filedata = []; - $source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; - } - - // Used to be foreach (scandir($source_dir, 1) as $file), but scandir() is simply not as fast - while (false !== ($file = readdir($fp))) - { - if (is_dir($source_dir . $file) && $file[0] !== '.' && $top_level_only === false) + $fp = @opendir($source_dir); { + // reset the array and make sure $source_dir has a trailing slash on the initial call + if ($recursion === false) { - get_dir_file_info($source_dir . $file . DIRECTORY_SEPARATOR, $top_level_only, true); + $filedata = []; + $source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; } - elseif ($file[0] !== '.') - { - $filedata[$file] = get_file_info($source_dir . $file); - $filedata[$file]['relative_path'] = $relative_path; - } - } - closedir($fp); - return $filedata; + // Used to be foreach (scandir($source_dir, 1) as $file), but scandir() is simply not as fast + while (false !== ($file = readdir($fp))) + { + if (is_dir($source_dir . $file) && $file[0] !== '.' && $top_level_only === false) + { + get_dir_file_info($source_dir . $file . DIRECTORY_SEPARATOR, $top_level_only, true); + } + elseif ($file[0] !== '.') + { + $filedata[$file] = get_file_info($source_dir . $file); + $filedata[$file]['relative_path'] = $relative_path; + } + } + + closedir($fp); + return $filedata; + } + } + catch (\Exception $fe) + { + return []; } - - return []; } } @@ -318,9 +337,9 @@ if ( ! function_exists('get_file_info')) * @param string $file Path to file * @param mixed $returned_values Array or comma separated string of information returned * - * @return array + * @return array|null */ - function get_file_info(string $file, $returned_values = ['name', 'server_path', 'size', 'date']): array + function get_file_info(string $file, $returned_values = ['name', 'server_path', 'size', 'date']) { if ( ! file_exists($file)) { @@ -334,8 +353,7 @@ if ( ! function_exists('get_file_info')) foreach ($returned_values as $key) { - switch ($key) - { + switch ($key) { case 'name': $fileinfo['name'] = basename($file); break; diff --git a/tests/system/Config/ConfigTest.php b/tests/system/Config/ConfigTest.php new file mode 100644 index 0000000000..b1e8397fff --- /dev/null +++ b/tests/system/Config/ConfigTest.php @@ -0,0 +1,40 @@ +assertInstanceOf(Email::class, $Config); + $this->assertInstanceOf(Email::class, $UpperConfig); + $this->assertInstanceOf(Email::class, $NamespaceConfig); + } + + public function testCreateInvalidInstance() + { + $Config = Config::get('gfnusvjai', false); + + $this->assertNull($Config); + } + + public function testCreateSharedInstance() + { + $Config = Config::get('email' ); + $Config2 = Config::get('Config\\Email'); + + $this->assertTrue($Config === $Config2); + } + + public function testCreateNonConfig() + { + $Config = Config::get('constants', false); + + $this->assertNull($Config); + } +} diff --git a/tests/system/HTTP/ResponseTest.php b/tests/system/HTTP/ResponseTest.php index 294fb00c80..58d01eec58 100644 --- a/tests/system/HTTP/ResponseTest.php +++ b/tests/system/HTTP/ResponseTest.php @@ -57,7 +57,7 @@ class ResponseTest extends \CIUnitTestCase $response = new Response(new App()); $this->expectException(HTTPException::class); - $this->expectExceptionMessage('Unknown HTTP status code provided with no message'); + $this->expectExceptionMessage(lang('HTTP.unknownStatusCode', [115])); $response->setStatusCode(115); } diff --git a/tests/system/Helpers/ArrayHelperTest.php b/tests/system/Helpers/ArrayHelperTest.php index 1db4d19f35..09b6ecd218 100644 --- a/tests/system/Helpers/ArrayHelperTest.php +++ b/tests/system/Helpers/ArrayHelperTest.php @@ -90,6 +90,22 @@ class ArrayHelperTest extends \CIUnitTestCase $this->assertEquals(23, dot_array_search('foo.*.baz', $data)); } + public function testArrayDotNestedNotFound() + { + $data = [ + 'foo' => [ + 'buzz' => [ + 'fizz' => 11 + ], + 'bar' => [ + 'baz' => 23 + ] + ] + ]; + + $this->assertNull(dot_array_search('foo.*.notthere', $data)); + } + public function testArrayDotIgnoresLastWildcard() { $data = [ diff --git a/tests/system/Helpers/CookieHelperTest.php b/tests/system/Helpers/CookieHelperTest.php index a361721cd7..e1ae2dfc02 100755 --- a/tests/system/Helpers/CookieHelperTest.php +++ b/tests/system/Helpers/CookieHelperTest.php @@ -4,7 +4,7 @@ use Config\App; use CodeIgniter\Config\Services; use Tests\Support\HTTP\MockResponse; -final class cookieHelperTest extends \CIUnitTestCase +final class CookieHelperTest extends \CIUnitTestCase { private $name; @@ -22,6 +22,8 @@ final class cookieHelperTest extends \CIUnitTestCase Services::injectMock('response', new MockResponse(new App())); $this->response = service('response'); + $this->request = new IncomingRequest(new App(), new URI(), null, new UserAgent()); + Services::injectMock('request', $this->request); helper('cookie'); } @@ -30,14 +32,11 @@ final class cookieHelperTest extends \CIUnitTestCase public function testSetCookie() { - $this->response->setCookie($this->name, $this->value, $this->expire); - - //TODO: Find a way for set_cookie() to use the MockResponse object. - //set_cookie($this->name, $this->value, $this->expire); + set_cookie($this->name, $this->value, $this->expire); $this->assertTrue($this->response->hasCookie($this->name)); - $this->response->deleteCookie($this->name); + delete_cookie($this->name); } //-------------------------------------------------------------------- @@ -49,17 +48,16 @@ final class cookieHelperTest extends \CIUnitTestCase 'value' => $this->value, 'expire' => $this->expire ]; - //set_cookie($cookieAttr); - $this->response->setCookie($cookieAttr); - + set_cookie($cookieAttr); + $this->assertTrue($this->response->hasCookie($this->name, $this->value)); - $this->response->deleteCookie($this->name); + delete_cookie($this->name); } //-------------------------------------------------------------------- - public function testGetCookie() + public function testSetCookieSecured() { $pre = 'Hello, I try to'; $pst = 'your site'; @@ -68,29 +66,35 @@ final class cookieHelperTest extends \CIUnitTestCase $unsecured = 'unsecured'; $secured = 'secured'; - //set_cookie($unsecured, $unsec, $this->expire); - //set_cookie($secured, $sec, $this->expire); - $this->response->setCookie($unsecured, $unsec, $this->expire); - $this->response->setCookie($secured, $sec, $this->expire); + set_cookie($unsecured, $unsec, $this->expire); + set_cookie($secured, $sec, $this->expire); $this->assertTrue($this->response->hasCookie($unsecured, $unsec)); $this->assertTrue($this->response->hasCookie($secured, $sec)); - $this->response->deleteCookie($unsecured); - $this->response->deleteCookie($secured); + delete_cookie($unsecured); + delete_cookie($secured); } //-------------------------------------------------------------------- public function testDeleteCookie() { - //set_cookie($this->name, $this->value, $this->expire); - $this->response->setCookie($this->name, $this->value, $this->expire); + set_cookie($this->name, $this->value, $this->expire); + //$this->response->setCookie($this->name, $this->value, $this->expire); - $this->response->deleteCookie($this->name); + delete_cookie($this->name); - //$this->assertEquals(get_cookie($this->name), ''); - $this->assertTrue($this->response->hasCookie($this->name)); + $this->assertEmpty($this->response->getCookie($this->name)); + } + + //-------------------------------------------------------------------- + + public function testGetCookie() + { + $_COOKIE['TEST'] = 5; + + $this->assertEquals(5, get_cookie('TEST')); } } diff --git a/tests/system/Helpers/DateHelperTest.php b/tests/system/Helpers/DateHelperTest.php new file mode 100644 index 0000000000..bb6bea584b --- /dev/null +++ b/tests/system/Helpers/DateHelperTest.php @@ -0,0 +1,37 @@ +assertLessThan(1, abs(now() - time())); // close enough + } + + //-------------------------------------------------------------------- + + public function testNowSpecific() + { + // Chicago should be two hours ahead of Vancouver + $this->assertEquals(7200,now('America/Chicago')-now('America/Vancouver')); + } + +} diff --git a/tests/system/Helpers/FilesystemHelperTest.php b/tests/system/Helpers/FilesystemHelperTest.php index cbf2c437a5..5df5deca00 100644 --- a/tests/system/Helpers/FilesystemHelperTest.php +++ b/tests/system/Helpers/FilesystemHelperTest.php @@ -1,298 +1,341 @@ -assertTrue(function_exists('directory_map')); + public function setUp() + { + parent::setUp(); - $structure = [ - 'foo' => [ - 'bar' => 'Once upon a midnight dreary', - 'baz' => 'While I pondered weak and weary' - ], - 'boo' => [ - 'far' => 'Upon a tome of long-forgotten lore', - 'faz' => 'There came a tapping up on the door' - ], - 'AnEmptyFolder' => [], - 'simpleFile' => 'A tap-tap-tapping upon my door', - '.hidden' => 'There is no spoon' - ]; + $this->structure = [ + 'foo' => [ + 'bar' => 'Once upon a midnight dreary', + 'baz' => 'While I pondered weak and weary' + ], + 'boo' => [ + 'far' => 'Upon a tome of long-forgotten lore', + 'faz' => 'There came a tapping up on the door' + ], + 'AnEmptyFolder' => [], + 'simpleFile' => 'A tap-tap-tapping upon my door', + '.hidden' => 'There is no spoon' + ]; + } - $expected = [ - 'foo' . DIRECTORY_SEPARATOR => [ - 'bar', - 'baz' - ], - 'boo' . DIRECTORY_SEPARATOR => [ - 'far', - 'faz' - ], - 'AnEmptyFolder' . DIRECTORY_SEPARATOR => [], - 'simpleFile' - ]; + //-------------------------------------------------------------------- - $root = vfsStream::setup('root', null, $structure); - $this->assertTrue($root->hasChild('foo')); + public function testDirectoryMapDefaults() + { + helper('filesystem'); + $this->assertTrue(function_exists('directory_map')); - $this->assertEquals($expected, directory_map(vfsStream::url('root'))); - } + $expected = [ + 'foo' . DIRECTORY_SEPARATOR => [ + 'bar', + 'baz' + ], + 'boo' . DIRECTORY_SEPARATOR => [ + 'far', + 'faz' + ], + 'AnEmptyFolder' . DIRECTORY_SEPARATOR => [], + 'simpleFile' + ]; - //-------------------------------------------------------------------- + $root = vfsStream::setup('root', null, $this->structure); + $this->assertTrue($root->hasChild('foo')); - public function testDirectoryMapShowsHiddenFiles() - { - helper('filesystem'); - $this->assertTrue(function_exists('directory_map')); + $this->assertEquals($expected, directory_map(vfsStream::url('root'))); + } - $structure = [ - 'foo' => [ - 'bar' => 'Once upon a midnight dreary', - 'baz' => 'While I pondered weak and weary' - ], - 'boo' => [ - 'far' => 'Upon a tome of long-forgotten lore', - 'faz' => 'There came a tapping up on the door' - ], - 'AnEmptyFolder' => [], - 'simpleFile' => 'A tap-tap-tapping upon my door', - '.hidden' => 'There is no spoon' - ]; + public function testDirectoryMapShowsHiddenFiles() + { + helper('filesystem'); + $this->assertTrue(function_exists('directory_map')); - $expected = [ - 'foo' . DIRECTORY_SEPARATOR => [ - 'bar', - 'baz' - ], - 'boo' . DIRECTORY_SEPARATOR => [ - 'far', - 'faz' - ], - 'AnEmptyFolder' . DIRECTORY_SEPARATOR => [], - 'simpleFile', - '.hidden' - ]; + $expected = [ + 'foo' . DIRECTORY_SEPARATOR => [ + 'bar', + 'baz' + ], + 'boo' . DIRECTORY_SEPARATOR => [ + 'far', + 'faz' + ], + 'AnEmptyFolder' . DIRECTORY_SEPARATOR => [], + 'simpleFile', + '.hidden' + ]; - $root = vfsStream::setup('root', null, $structure); - $this->assertTrue($root->hasChild('foo')); + $root = vfsStream::setup('root', null, $this->structure); + $this->assertTrue($root->hasChild('foo')); - $this->assertEquals($expected, directory_map(vfsStream::url('root'), false, true)); - } + $this->assertEquals($expected, directory_map(vfsStream::url('root'), false, true)); + } - //-------------------------------------------------------------------- + public function testDirectoryMapLimitsRecursion() + { + $this->assertTrue(function_exists('directory_map')); - public function testDirectoryMapLimitsRecursion() - { - $this->assertTrue(function_exists('directory_map')); + $expected = [ + 'foo' . DIRECTORY_SEPARATOR, + 'boo' . DIRECTORY_SEPARATOR, + 'AnEmptyFolder' . DIRECTORY_SEPARATOR, + 'simpleFile', + '.hidden' + ]; - $structure = [ - 'foo' => [ - 'bar' => 'Once upon a midnight dreary', - 'baz' => 'While I pondered weak and weary' - ], - 'boo' => [ - 'far' => 'Upon a tome of long-forgotten lore', - 'faz' => 'There came a tapping up on the door' - ], - 'AnEmptyFolder' => [], - 'simpleFile' => 'A tap-tap-tapping upon my door', - '.hidden' => 'There is no spoon' - ]; + $root = vfsStream::setup('root', null, $this->structure); + $this->assertTrue($root->hasChild('foo')); - $expected = [ - 'foo' . DIRECTORY_SEPARATOR, - 'boo' . DIRECTORY_SEPARATOR, - 'AnEmptyFolder' . DIRECTORY_SEPARATOR, - 'simpleFile', - '.hidden' - ]; + $this->assertEquals($expected, directory_map(vfsStream::url('root'), 1, true)); + } - $root = vfsStream::setup('root', null, $structure); - $this->assertTrue($root->hasChild('foo')); + public function testDirectoryMapHandlesNotfound() + { + $this->assertEquals([], directory_map(SUPPORTPATH . 'Files/shaker/')); + } - $this->assertEquals($expected, directory_map(vfsStream::url('root'), 1, true)); - } + //-------------------------------------------------------------------- - //-------------------------------------------------------------------- + public function testWriteFileSuccess() + { + $vfs = vfsStream::setup('root'); - public function testWriteFileSuccess() - { - $vfs = vfsStream::setup('root'); + $this->assertTrue(write_file(vfsStream::url('root/test.php'), 'Simple')); + $this->assertFileExists($vfs->getChild('test.php')->url()); + } - $this->assertTrue(write_file(vfsStream::url('root/test.php'), 'Simple')); - $this->assertFileExists($vfs->getChild('test.php')->url()); - } + public function testWriteFileFailure() + { + $vfs = vfsStream::setup('root'); - //-------------------------------------------------------------------- + $this->assertFalse(write_file(vfsStream::url('apple#test.php'), 'Simple')); + } - public function testDeleteFilesDefaultsToOneLevelDeep() - { - $this->assertTrue(function_exists('delete_files')); + //-------------------------------------------------------------------- - $structure = [ - 'foo' => [ - 'bar' => 'Once upon a midnight dreary', - 'baz' => 'While I pondered weak and weary' - ], - 'boo' => [ - 'far' => 'Upon a tome of long-forgotten lore', - 'faz' => 'There came a tapping up on the door' - ], - 'AnEmptyFolder' => [], - 'simpleFile' => 'A tap-tap-tapping upon my door', - '.hidden' => 'There is no spoon' - ]; + public function testDeleteFilesDefaultsToOneLevelDeep() + { + $this->assertTrue(function_exists('delete_files')); - $vfs = vfsStream::setup('root', null, $structure); + $vfs = vfsStream::setup('root', null, $this->structure); - delete_files(vfsStream::url('root')); + delete_files(vfsStream::url('root')); - $this->assertFalse($vfs->hasChild('simpleFile')); - $this->assertFalse($vfs->hasChild('.hidden')); - $this->assertTrue($vfs->hasChild('foo')); - $this->assertTrue($vfs->hasChild('boo')); - $this->assertTrue($vfs->hasChild('AnEmptyFolder')); - } + $this->assertFalse($vfs->hasChild('simpleFile')); + $this->assertFalse($vfs->hasChild('.hidden')); + $this->assertTrue($vfs->hasChild('foo')); + $this->assertTrue($vfs->hasChild('boo')); + $this->assertTrue($vfs->hasChild('AnEmptyFolder')); + } - //-------------------------------------------------------------------- + public function testDeleteFilesHandlesRecursion() + { + $this->assertTrue(function_exists('delete_files')); - public function testDeleteFilesHandlesRecursion() - { - $this->assertTrue(function_exists('delete_files')); + $vfs = vfsStream::setup('root', null, $this->structure); - $structure = [ - 'foo' => [ - 'bar' => 'Once upon a midnight dreary', - 'baz' => 'While I pondered weak and weary' - ], - 'boo' => [ - 'far' => 'Upon a tome of long-forgotten lore', - 'faz' => 'There came a tapping up on the door' - ], - 'AnEmptyFolder' => [], - 'simpleFile' => 'A tap-tap-tapping upon my door', - '.hidden' => 'There is no spoon' - ]; + delete_files(vfsStream::url('root'), true); - $vfs = vfsStream::setup('root', null, $structure); + $this->assertFalse($vfs->hasChild('simpleFile')); + $this->assertFalse($vfs->hasChild('.hidden')); + $this->assertFalse($vfs->hasChild('foo')); + $this->assertFalse($vfs->hasChild('boo')); + $this->assertFalse($vfs->hasChild('AnEmptyFolder')); + } - delete_files(vfsStream::url('root'), true); + public function testDeleteFilesLeavesHTFiles() + { + $structure = array_merge($this->structure, [ + '.htaccess' => 'Deny All', + 'index.html' => 'foo', + 'index.php' => 'blah' + ]); - $this->assertFalse($vfs->hasChild('simpleFile')); - $this->assertFalse($vfs->hasChild('.hidden')); - $this->assertFalse($vfs->hasChild('foo')); - $this->assertFalse($vfs->hasChild('boo')); - $this->assertFalse($vfs->hasChild('AnEmptyFolder')); - } + $vfs = vfsStream::setup('root', null, $structure); - //-------------------------------------------------------------------- + delete_files(vfsStream::url('root'), true, true); - public function testDeleteFilesLeavesHTFiles() - { - $structure = [ - 'foo' => [ - 'bar' => 'Once upon a midnight dreary', - 'baz' => 'While I pondered weak and weary' - ], - 'boo' => [ - 'far' => 'Upon a tome of long-forgotten lore', - 'faz' => 'There came a tapping up on the door' - ], - 'AnEmptyFolder' => [], - 'simpleFile' => 'A tap-tap-tapping upon my door', - '.hidden' => 'There is no spoon', - '.htaccess' => 'Deny All', - 'index.html' => 'foo', - 'index.php' => 'blah' - ]; + $this->assertFalse($vfs->hasChild('simpleFile')); + $this->assertFalse($vfs->hasChild('foo')); + $this->assertFalse($vfs->hasChild('boo')); + $this->assertFalse($vfs->hasChild('AnEmptyFolder')); + $this->assertTrue($vfs->hasChild('.htaccess')); + $this->assertTrue($vfs->hasChild('index.html')); + $this->assertTrue($vfs->hasChild('index.php')); + } - $vfs = vfsStream::setup('root', null, $structure); + public function testDeleteFilesFailure() + { + $this->assertFalse(delete_files(SUPPORTPATH . 'Files/shaker/')); + } - delete_files(vfsStream::url('root'), true, true); + //-------------------------------------------------------------------- - $this->assertFalse($vfs->hasChild('simpleFile')); - $this->assertFalse($vfs->hasChild('foo')); - $this->assertFalse($vfs->hasChild('boo')); - $this->assertFalse($vfs->hasChild('AnEmptyFolder')); - $this->assertTrue($vfs->hasChild('.htaccess')); - $this->assertTrue($vfs->hasChild('index.html')); - $this->assertTrue($vfs->hasChild('index.php')); - } + public function testGetFilenames() + { + $this->assertTrue(function_exists('delete_files')); - //-------------------------------------------------------------------- + // Not sure the directory names should actually show up + // here but this matches v3.x results. + $expected = [ + 'foo', + 'boo', + 'AnEmptyFolder', + 'simpleFile' + ]; - public function testGetFilenames() - { - $this->assertTrue(function_exists('delete_files')); + $vfs = vfsStream::setup('root', null, $this->structure); - $structure = [ - 'foo' => [ - 'bar' => 'Once upon a midnight dreary', - 'baz' => 'While I pondered weak and weary' - ], - 'boo' => [ - 'far' => 'Upon a tome of long-forgotten lore', - 'faz' => 'There came a tapping up on the door' - ], - 'AnEmptyFolder' => [], - 'simpleFile' => 'A tap-tap-tapping upon my door', - '.hidden' => 'There is no spoon' - ]; + $this->assertEquals($expected, get_filenames($vfs->url(), false)); + } - // Not sure the directory names should actually show up - // here but this matches v3.x results. - $expected = [ - 'foo', - 'boo', - 'AnEmptyFolder', - 'simpleFile' - ]; + public function testGetFilenamesWithSource() + { + $this->assertTrue(function_exists('delete_files')); - $vfs = vfsStream::setup('root', null, $structure); + // Not sure the directory names should actually show up + // here but this matches v3.x results. + $expected = [ + DIRECTORY_SEPARATOR . 'foo', + DIRECTORY_SEPARATOR . 'boo', + DIRECTORY_SEPARATOR . 'AnEmptyFolder', + DIRECTORY_SEPARATOR . 'simpleFile' + ]; - $this->assertEquals($expected, get_filenames($vfs->url(), false)); - } + $vfs = vfsStream::setup('root', null, $this->structure); - //-------------------------------------------------------------------- + $this->assertEquals($expected, get_filenames($vfs->url(), true)); + } - public function testGetFilenamesWithSource() - { - $this->assertTrue(function_exists('delete_files')); + public function testGetFilenamesFailure() + { + $this->assertEquals([], get_filenames(SUPPORTPATH . 'Files/shaker/')); + } - $structure = [ - 'foo' => [ - 'bar' => 'Once upon a midnight dreary', - 'baz' => 'While I pondered weak and weary' - ], - 'boo' => [ - 'far' => 'Upon a tome of long-forgotten lore', - 'faz' => 'There came a tapping up on the door' - ], - 'AnEmptyFolder' => [], - 'simpleFile' => 'A tap-tap-tapping upon my door', - '.hidden' => 'There is no spoon' - ]; + //-------------------------------------------------------------------- - // Not sure the directory names should actually show up - // here but this matches v3.x results. - $expected = [ - DIRECTORY_SEPARATOR . 'foo', - DIRECTORY_SEPARATOR . 'boo', - DIRECTORY_SEPARATOR . 'AnEmptyFolder', - DIRECTORY_SEPARATOR . 'simpleFile' - ]; + public function testGetDirFileInfo() + { + $expected = [ + 'banana.php' => [ + 'name' => 'banana.php', + 'server_path' => '/pub7/htdocs/CodeIgniter4/tests/_support/Files/baker/banana.php', + 'size' => 193, + 'date' => 1529305930, + 'relative_path' => '/pub7/htdocs/CodeIgniter4/tests/_support/Files/baker', + ] + ]; - $vfs = vfsStream::setup('root', null, $structure); - $this->assertEquals($expected, get_filenames($vfs->url(), true)); - } + $this->assertEquals($expected, get_dir_file_info(SUPPORTPATH . 'Files/baker')); + } - //-------------------------------------------------------------------- + public function testGetDirFileInfoNested() + { + $expected = ['banana.php', 'prune_ripe.php', 'fig_3.php', 'apple.php']; + $results = get_dir_file_info(SUPPORTPATH . 'Files', false); + $this->assertEmpty(array_diff($expected, array_keys($results))); + } + + public function testGetDirFileInfoFailure() + { + $expected = []; + + $this->assertEquals($expected, get_dir_file_info(SUPPORTPATH . 'Files#baker')); + } + + //-------------------------------------------------------------------- + + public function testGetFileInfo() + { + $expected = [ + 'name' => 'banana.php', + 'server_path' => '/pub7/htdocs/CodeIgniter4/tests/_support/Files/baker/banana.php', + 'size' => 193, + 'date' => 1529305930, + ]; + + + $this->assertEquals($expected, get_file_info(SUPPORTPATH . 'Files/baker/banana.php')); + } + + public function testGetFileInfoCustom() + { + $expected = [ + 'readable' => true, + 'writable' => true, + 'executable' => false, + ]; + + $this->assertEquals($expected, get_file_info(SUPPORTPATH . 'Files/baker/banana.php', 'readable,writable,executable')); + } + + public function testGetFileInfoPerms() + { + $expected = 0664; + + $stuff = get_file_info(SUPPORTPATH . 'Files/baker/banana.php', 'fileperms'); + $this->assertEquals($expected, $stuff['fileperms'] & 0777); + } + + public function testGetFileNotThereInfo() + { + $expected = null; + + $this->assertEquals($expected, get_file_info(SUPPORTPATH . 'Files/icer')); + } + + //-------------------------------------------------------------------- + public function testOctalPermissions() + { + $this->assertEquals('777', octal_permissions(0777)); + $this->assertEquals('655', octal_permissions(0655)); + $this->assertEquals('123', octal_permissions(0123)); + } + + public function testSymbolicPermissions() + { + $expected = [ + 0777 => 'urwxrwxrwx', + 0655 => 'urw-r-xr-x', + 0123 => 'u--x-w--wx', + 010655 => 'prw-r-xr-x', + 020655 => 'crw-r-xr-x', + 040655 => 'drw-r-xr-x', + 060655 => 'brw-r-xr-x', + 0100655 => '-rw-r-xr-x', + 0120655 => 'lrw-r-xr-x', + 0140655 => 'srw-r-xr-x', + ]; + + foreach ($expected as $perm => $value) + $this->assertEquals($value, symbolic_permissions($perm)); + } + + //-------------------------------------------------------------------- + + public function testRealPathURL() + { + $this->expectException(\InvalidArgumentException::class); + set_realpath('http://somewhere.com/overtherainbow'); + } + + public function testRealPathInvalid() + { + $this->expectException(\InvalidArgumentException::class); + set_realpath(SUPPORTPATH . 'root/../', true); + } + + public function testRealPathResolved() + { + $this->assertEquals(SUPPORTPATH . 'Helpers/', set_realpath(SUPPORTPATH . 'Files/../Helpers', true)); + } } diff --git a/user_guide_src/source/general/configuration.rst b/user_guide_src/source/general/configuration.rst index af63b1b05d..cd3860602e 100644 --- a/user_guide_src/source/general/configuration.rst +++ b/user_guide_src/source/general/configuration.rst @@ -11,11 +11,21 @@ create an instance of the class and all your settings are there for you. Accessing Config Files ====================== -You can access config files within your classes by creating a new instance. All of the properties +You can access config files within your classes by creating a new instance or using the config function. All of the properties are public, so you access the settings like any other property:: + // Creating new class by hand $config = new \Config\EmailConfig(); + // Creating new class with config function + $config = config( 'EmailConfig', false ); + + // Get shared instance with config function + $config = config( 'EmailConfig' ); + + // Access config class with namespace + $config = config( 'Config\\EmailConfig' ); + // Access settings as class properties $protocol = $config->protocol; $mailpath = $config->mailpath; diff --git a/user_guide_src/source/helpers/date_helper.rst b/user_guide_src/source/helpers/date_helper.rst new file mode 100644 index 0000000000..e6d451f4fe --- /dev/null +++ b/user_guide_src/source/helpers/date_helper.rst @@ -0,0 +1,47 @@ +########### +Date Helper +########### + +The Date Helper file contains functions that assist in working with +dates. + +.. contents:: + :local: + +.. raw:: html + +
+ +Loading this Helper +=================== + +This helper is loaded using the following code:: + + helper('date'); + +Available Functions +=================== + +The following functions are available: + +.. php:function:: now([$timezone = NULL]) + + :param string $timezone: Timezone + :returns: UNIX timestamp + :rtype: int + + Returns the current time as a UNIX timestamp, referenced either to your server's + local time or any PHP supported timezone, based on the "time reference" setting + in your config file. If you do not intend to set your master time reference to + any other PHP supported timezone (which you'll typically do if you run a site + that lets each user set their own timezone settings) there is no benefit to using + this function over PHP's ``time()`` function. + :: + + echo now('Australia/Victoria'); + + If a timezone is not provided, it will return ``time()`` based on the + **time_reference** setting. + +Many functions previously found in the CodeIgniter 3 ``date_helper`` have been moved to the ``I18n`` +module in CodeIgniter 4. diff --git a/user_guide_src/source/index.rst b/user_guide_src/source/index.rst index f45a13da35..b4685abf13 100644 --- a/user_guide_src/source/index.rst +++ b/user_guide_src/source/index.rst @@ -44,9 +44,9 @@ Tutorial CodeIgniter4 Overview ********************* .. toctree:: - :titlesonly: + :titlesonly: - concepts/index + concepts/index ************** General Topics @@ -61,7 +61,10 @@ General Topics Library Reference ***************** -* ``Honeypot`` +.. toctree:: + :titlesonly: + + libraries/index ****************** Database Reference @@ -86,9 +89,9 @@ Testing ******* .. toctree:: - :titlesonly: + :titlesonly: - testing.index + testing/index *************************** Contributing to CodeIgniter @@ -97,4 +100,4 @@ Contributing to CodeIgniter .. toctree:: :titlesonly: - contributing/index + contributing/index diff --git a/user_guide_src/source/libraries/index.rst b/user_guide_src/source/libraries/index.rst index 668cbebb72..c14b7d04b8 100644 --- a/user_guide_src/source/libraries/index.rst +++ b/user_guide_src/source/libraries/index.rst @@ -13,6 +13,7 @@ Library Reference curlrequest email files + honeypot images incomingrequest localization