diff --git a/composer.json b/composer.json index f45d6de..3fc58fa 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ }, "require-dev": { "pestphp/pest": "^3.2", - "laravel/pint": "^1.1" + "laravel/pint": "^1.1", + "mockery/mockery": "^1.6" }, "scripts": { "lint": ["pint"], diff --git a/composer.lock b/composer.lock index e9cdc8d..181d56b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a249ff1cf1e50817ac4d193bd893f830", + "content-hash": "fc80f514b6bf09d7ce5985191795cdff", "packages": [ { "name": "dflydev/dot-access-data", @@ -1481,6 +1481,57 @@ ], "time": "2023-11-03T12:00:00+00:00" }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "shasum": "" + }, + "require": { + "php": "^5.3|^7.0|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + }, + "time": "2020-07-09T08:09:16+00:00" + }, { "name": "jean85/pretty-package-versions", "version": "2.0.6", @@ -1606,6 +1657,89 @@ }, "time": "2024-09-24T17:22:50+00:00" }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2024-05-16T03:13:13+00:00" + }, { "name": "myclabs/deep-copy", "version": "1.12.0", diff --git a/src/ContentType.php b/src/ContentType.php index fcb4fc5..49a6ab6 100644 --- a/src/ContentType.php +++ b/src/ContentType.php @@ -6,6 +6,9 @@ use Parsed\ContentParser; +/** + * A ContentType is a node with either children nodes or content files + */ class ContentType { public string $slug; diff --git a/src/Provider/ContentServiceProvider.php b/src/Provider/ContentServiceProvider.php index dd44e77..346f5a5 100644 --- a/src/Provider/ContentServiceProvider.php +++ b/src/Provider/ContentServiceProvider.php @@ -94,6 +94,10 @@ public function fetchAll(int $start = 0, int $limit = 20, bool $parse_markdown = } catch (Exception $e) { } } + + if (count($contentType->children)) { + + } } $list = $this->orderBy($list, $orderBy); diff --git a/src/Request.php b/src/Request.php index d668873..6884bd8 100644 --- a/src/Request.php +++ b/src/Request.php @@ -6,22 +6,38 @@ class Request { + /** + * Parameters from Request + */ protected array $params; + /** + * The full request string + */ protected string $request_uri; + /** + * Request information + */ protected ?array $request_info; + /** + * Full request path + */ protected string $path; /** - * @var string Requested route, such as "home", "index", "blog", etc - * only 1 level is supported + * The root of the path */ protected string $route; /** - * @var string Slug if present (request path minus route) + * Parent route, used for content types + */ + protected string $parent; + + /** + * Final portion of the request string, when present */ protected string $slug; @@ -33,10 +49,9 @@ public function __construct(array $params, string $request_uri) $this->request_info = parse_url($this->request_uri); $this->path = $this->request_info['path']; - //make sure to get the first part only $parts = explode('/', $this->path); - $this->route = $parts[1]; + $this->parent = dirname($this->path); $this->slug = str_replace('/' . $this->route . '/', '', $this->path); } @@ -69,4 +84,9 @@ public function getSlug(): string { return $this->slug; } + + public function getParent(): string + { + return $this->parent; + } } diff --git a/tests/Feature/ContentTest.php b/tests/Feature/ContentTest.php index 1a7c9f5..8af79b3 100644 --- a/tests/Feature/ContentTest.php +++ b/tests/Feature/ContentTest.php @@ -47,7 +47,7 @@ it('loads the full list of content when no limit is passed', function () { $content = $this->app->content->fetchAll(0, 0); expect($content)->toBeInstanceOf(ContentCollection::class) - ->and($content->total())->toBeGreaterThan(2); + ->and($content->total())->toBe(5); }); it('loads tag list', function () { diff --git a/tests/Feature/RequestTest.php b/tests/Feature/RequestTest.php new file mode 100644 index 0000000..981f689 --- /dev/null +++ b/tests/Feature/RequestTest.php @@ -0,0 +1,49 @@ +config = [ + 'debug' => true, + 'templates_path' => __DIR__ . '/../resources', + 'data_path' => __DIR__ . '/../resources', + 'cache_path' => __DIR__ . '/../resources', + ]; + + $request = new Request(['param1' => 'value1', 'param2' => 'value2'], '/docs/en/test0'); + $router = Mockery::mock(RouterServiceProvider::class); + $router->shouldReceive('load'); + $router->shouldReceive('getRequest')->andReturn($request); + + $app = new App($this->config); + $app->addService('content', new ContentServiceProvider()); + $app->addService('twig', new TwigServiceProvider()); + $app->addService('librarian', new LibrarianServiceProvider()); + $app->addService('router', $router); + $this->app = $app; +}); + +it('passes request through router', function () { + $request = $this->app->router->getRequest(); + expect($request)->toBeInstanceOf(Request::class) + ->and($request->getParams())->toBe(['param1' => 'value1', 'param2' => 'value2']); +}); + +it('loads content in nested structure', function () { + $request = $this->app->router->getRequest(); + expect($request->getRoute())->toBe('docs') + ->and($request->getParent())->toBe('/docs/en') + ->and($request->getSlug())->toBe('en/test0'); + + $contentType = $this->app->content->getContentType($request->getParent()); + expect($contentType)->toBeInstanceOf(ContentType::class) + ->and($contentType->title)->toBe('English Docs'); +});