diff --git a/.gitignore b/.gitignore
index 52c8085..4434dac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
.DS_Store
+.phpunit.result.cache
/vendor
/composer.lock
diff --git a/README.md b/README.md
index 47f5d63..4ca2d9b 100644
--- a/README.md
+++ b/README.md
@@ -63,7 +63,7 @@ You can also exclude single routes, or route groups with wildcards. This will ov
],
```
-### Dynamically adding routes
+### Dynamic Routes
You may add URLs dynamically by providing a closure that returns an array to the `addUrls` method.
@@ -81,6 +81,16 @@ class AppServiceProvider extends Provider
}
```
+### Pagination Routes
+
+Wherever pagination is detected in your antlers templates (eg. if you use the `paginate` param on the `collection` tag), multiple pages will automatically be generated with `/articles/page/2` style urls.
+
+You may configure a custom routing style in `config/statamic/ssg.php`:
+
+```php
+'pagination_route' => '{url}/{page_name}/{page_number}',
+```
+
## Post-generation callback
diff --git a/config/ssg.php b/config/ssg.php
index e3436ab..ae331a4 100644
--- a/config/ssg.php
+++ b/config/ssg.php
@@ -73,6 +73,19 @@
//
],
+ /*
+ |--------------------------------------------------------------------------
+ | Pagination Route
+ |--------------------------------------------------------------------------
+ |
+ | Here you may define how paginated entries are routed. This will take
+ | effect wherever pagination is detected in your antlers templates,
+ | like if you use the `paginate` param on the `collection` tag.
+ |
+ */
+
+ 'pagination_route' => '{url}/{page_name}/{page_number}',
+
/*
|--------------------------------------------------------------------------
| Glide
diff --git a/phpunit.xml b/phpunit.xml
index b2b92bb..bfc27ff 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -18,5 +18,7 @@
+
+
diff --git a/src/LengthAwarePaginator.php b/src/LengthAwarePaginator.php
new file mode 100644
index 0000000..edbdb45
--- /dev/null
+++ b/src/LengthAwarePaginator.php
@@ -0,0 +1,39 @@
+path(), $this->getPageName(), $page);
+
+ if (Str::contains($this->path(), '?') || count($this->query)) {
+ $url .= '?'.Arr::query($this->query);
+ }
+
+ return $url.$this->buildFragment();
+ }
+
+ public static function generatePaginatedUrl($url, $pageName, $pageNumber)
+ {
+ $route = config('statamic.ssg.pagination_route');
+
+ $url = str_replace('{url}', $url, $route);
+
+ $url = str_replace('{page_name}', $pageName, $url);
+
+ $url = str_replace('{page_number}', $pageNumber, $url);
+
+ return URL::makeRelative($url);
+ }
+}
diff --git a/src/Page.php b/src/Page.php
index 6c3ff1d..1145d1f 100644
--- a/src/Page.php
+++ b/src/Page.php
@@ -6,12 +6,15 @@
use Illuminate\Filesystem\Filesystem;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Http\RedirectResponse;
+use Statamic\Facades\Blink;
class Page
{
protected $files;
protected $config;
protected $content;
+ protected $paginationPageName;
+ protected $paginationCurrentPage;
public function __construct(Filesystem $files, array $config, $content)
{
@@ -33,14 +36,24 @@ public function isGeneratable()
public function generate($request)
{
try {
- return $this->write($request);
+ $generatedPage = $this->write($request);
} catch (Exception $e) {
throw new NotGeneratedException($this, $e);
}
+
+ if ($paginator = $this->detectPaginator($request)) {
+ $this->writePaginatedPages($request, $paginator);
+ }
+
+ return $generatedPage;
}
protected function write($request)
{
+ if ($this->paginationPageName) {
+ $request->merge([$this->paginationPageName => $this->paginationCurrentPage]);
+ }
+
try {
$response = $this->content->toResponse($request);
} catch (HttpResponseException $e) {
@@ -59,6 +72,23 @@ protected function write($request)
return new GeneratedPage($this, $response);
}
+ protected function writePaginatedPages($request, $paginator)
+ {
+ collect(range(1, $paginator->lastPage()))->each(function ($pageNumber) use ($request) {
+ $page = clone $this;
+
+ try {
+ $page
+ ->setPaginationCurrentPage($pageNumber)
+ ->write($request);
+ } catch (Exception $e) {
+ throw new NotGeneratedException($page, $e);
+ }
+ });
+
+ $this->clearPaginator($request);
+ }
+
public function directory()
{
return dirname($this->path());
@@ -85,7 +115,17 @@ public function path()
public function url()
{
- return $this->content->urlWithoutRedirect();
+ $url = $this->content->urlWithoutRedirect();
+
+ if ($this->paginationCurrentPage) {
+ $url = LengthAwarePaginator::generatePaginatedUrl(
+ $url,
+ $this->paginationPageName,
+ $this->paginationCurrentPage
+ );
+ }
+
+ return $url;
}
public function site()
@@ -97,4 +137,31 @@ public function is404()
{
return $this->url() === '/404';
}
+
+ public function setPaginationCurrentPage($currentPage)
+ {
+ $this->paginationCurrentPage = $currentPage;
+
+ return $this;
+ }
+
+ protected function detectPaginator($request)
+ {
+ if ($paginator = Blink::get('tag-paginator')) {
+ $this->paginationPageName = $paginator->getPageName();
+ }
+
+ $this->clearPaginator($request);
+
+ return $paginator;
+ }
+
+ protected function clearPaginator($request)
+ {
+ Blink::forget('tag-paginator');
+
+ if ($this->paginationPageName) {
+ $request->forget($this->paginationPageName);
+ }
+ }
}
diff --git a/src/Request.php b/src/Request.php
index 5624f33..e785114 100644
--- a/src/Request.php
+++ b/src/Request.php
@@ -61,4 +61,11 @@ public function path()
return ltrim($path, '/');
}
+
+ public function forget(string $inputKey)
+ {
+ $this->getInputSource()->remove($inputKey);
+
+ return $this;
+ }
}
diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php
index 48d7e12..ec883c0 100644
--- a/src/ServiceProvider.php
+++ b/src/ServiceProvider.php
@@ -4,13 +4,16 @@
use Illuminate\Support\ServiceProvider as LaravelServiceProvider;
use Spatie\Fork\Fork;
+use Statamic\Extensions\Pagination\LengthAwarePaginator as StatamicLengthAwarePaginator;
class ServiceProvider extends LaravelServiceProvider
{
public function register()
{
+ $this->app->bind('fork-installed', fn () => class_exists(Fork::class));
+
$this->app->bind(Tasks::class, function ($app) {
- return $app->runningInConsole() && class_exists(Fork::class)
+ return $app->runningInConsole() && $app['fork-installed']
? new ConcurrentTasks(new Fork)
: new ConsecutiveTasks;
});
@@ -33,5 +36,17 @@ public function boot()
Commands\StaticSiteServe::class,
]);
}
+
+ if ($this->app->runningInConsole()) {
+ $this->app->extend(StatamicLengthAwarePaginator::class, function ($paginator) {
+ return $this->app->makeWith(LengthAwarePaginator::class, [
+ 'items' => $paginator->getCollection(),
+ 'total' => $paginator->total(),
+ 'perPage' => $paginator->perPage(),
+ 'currentPage' => $paginator->currentPage(),
+ 'options' => $paginator->getOptions(),
+ ]);
+ });
+ }
}
}
diff --git a/tests/Concerns/RunsGeneratorCommand.php b/tests/Concerns/RunsGeneratorCommand.php
new file mode 100644
index 0000000..afe5ebe
--- /dev/null
+++ b/tests/Concerns/RunsGeneratorCommand.php
@@ -0,0 +1,77 @@
+destination = storage_path('app/static');
+
+ $this->cleanUpDestination();
+ }
+
+ public function tearDown(): void
+ {
+ $this->cleanUpDestination();
+
+ parent::tearDown();
+ }
+
+ protected function generate()
+ {
+ $this->assertFalse($this->files->exists($this->destination));
+
+ $this
+ ->artisan('statamic:ssg:generate')
+ ->doesntExpectOutputToContain('pages not generated');
+
+ $this->assertTrue($this->files->exists($this->destination));
+
+ return $this->getGeneratedFilesAtPath($this->destination);
+ }
+
+ protected function relativePath($path)
+ {
+ return str_replace(Path::tidy($this->destination.'/'), '', Path::tidy($path));
+ }
+
+ protected function destinationPath($path)
+ {
+ return Path::tidy($this->destination.'/'.$path);
+ }
+
+ protected function getGeneratedFilesAtPath($path)
+ {
+ return collect($this->files->allFiles($path))
+ ->mapWithKeys(fn ($file) => [$this->relativePath($file->getPathname()) => $file->getContents()])
+ ->all();
+ }
+
+ protected function cleanUpDestination($destination = null)
+ {
+ $destination ??= $this->destination;
+
+ if ($this->files->exists($destination)) {
+ $this->files->deleteDirectory($destination);
+ }
+ }
+
+ protected function assertStringContainsStrings($needleStrings, $haystackString)
+ {
+ foreach ($needleStrings as $string) {
+ $this->assertStringContainsString($string, $haystackString);
+ }
+ }
+
+ protected function assertStringNotContainsStrings($needleStrings, $haystackString)
+ {
+ foreach ($needleStrings as $string) {
+ $this->assertStringNotContainsString($string, $haystackString);
+ }
+ }
+}
diff --git a/tests/Fixtures/resources/views/articles/index.antlers.html b/tests/Fixtures/resources/views/articles/index.antlers.html
new file mode 100644
index 0000000..bdc4e10
--- /dev/null
+++ b/tests/Fixtures/resources/views/articles/index.antlers.html
@@ -0,0 +1,4 @@
+
Articles Index Page Title
+{{ collection:articles sort="date:asc" }}
+ {{ title }}
+{{ /collection:articles }}
diff --git a/tests/Fixtures/resources/views/articles/show.antlers.html b/tests/Fixtures/resources/views/articles/show.antlers.html
new file mode 100644
index 0000000..e941cd1
--- /dev/null
+++ b/tests/Fixtures/resources/views/articles/show.antlers.html
@@ -0,0 +1,2 @@
+Article Title: {{ title }}
+Content: {{ content }}
diff --git a/tests/Fixtures/resources/views/default.antlers.html b/tests/Fixtures/resources/views/default.antlers.html
new file mode 100644
index 0000000..924fad5
--- /dev/null
+++ b/tests/Fixtures/resources/views/default.antlers.html
@@ -0,0 +1,2 @@
+Page Title: {{ title }}
+Content: {{ content }}
diff --git a/tests/Fixtures/resources/views/errors/404.antlers.html b/tests/Fixtures/resources/views/errors/404.antlers.html
new file mode 100644
index 0000000..d78be50
--- /dev/null
+++ b/tests/Fixtures/resources/views/errors/404.antlers.html
@@ -0,0 +1 @@
+404!
diff --git a/tests/Fixtures/resources/views/layout.antlers.html b/tests/Fixtures/resources/views/layout.antlers.html
new file mode 100644
index 0000000..82b8e00
--- /dev/null
+++ b/tests/Fixtures/resources/views/layout.antlers.html
@@ -0,0 +1,2 @@
+{{ seo_pro:meta }}
+{{ template_content }}
diff --git a/tests/Fixtures/site-localized/content/collections/articles.yaml b/tests/Fixtures/site-localized/content/collections/articles.yaml
new file mode 100644
index 0000000..d91eadc
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles.yaml
@@ -0,0 +1,16 @@
+title: Articles
+sites:
+ - default
+ - french
+route:
+ default: 'articles/{slug}'
+ french: 'le-articles/{slug}'
+template: articles.show
+mount: b9e4bfe3-9c12-4553-b7ef-f43c22ffaa63
+taxonomies:
+ - topics
+revisions: false
+date: true
+date_behavior:
+ past: public
+ future: private
diff --git a/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-01.one.md b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-01.one.md
new file mode 100644
index 0000000..9792983
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-01.one.md
@@ -0,0 +1,4 @@
+---
+id: a356f052-06a3-4f37-8376-2f136fe973c3
+title: One
+---
diff --git a/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-02.two.md b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-02.two.md
new file mode 100644
index 0000000..107524b
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-02.two.md
@@ -0,0 +1,4 @@
+---
+id: ca648856-ff12-407d-a523-72074f5997e1
+title: Two
+---
diff --git a/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-03.three.md b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-03.three.md
new file mode 100644
index 0000000..059a10f
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-03.three.md
@@ -0,0 +1,4 @@
+---
+id: 312dff5e-4d4e-44bd-ac47-80ef58278675
+title: Three
+---
diff --git a/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-04.four.md b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-04.four.md
new file mode 100644
index 0000000..b3d4282
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-04.four.md
@@ -0,0 +1,4 @@
+---
+id: d813ea6f-a637-4c6b-a724-c9e5f70e23de
+title: Four
+---
diff --git a/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-05.five.md b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-05.five.md
new file mode 100644
index 0000000..38d8f24
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-05.five.md
@@ -0,0 +1,4 @@
+---
+id: 3a2e2f92-f93e-481d-b120-c63ff09c1775
+title: Five
+---
diff --git a/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-06.six.md b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-06.six.md
new file mode 100644
index 0000000..d544613
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-06.six.md
@@ -0,0 +1,4 @@
+---
+id: c72306d0-b6ae-4f3a-88eb-6c01d5a83c0d
+title: Six
+---
diff --git a/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-07.seven.md b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-07.seven.md
new file mode 100644
index 0000000..a5c56a5
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-07.seven.md
@@ -0,0 +1,4 @@
+---
+id: 6614e8af-4c11-4790-a47e-ebb6b685851d
+title: Seven
+---
diff --git a/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-08.eight.md b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-08.eight.md
new file mode 100644
index 0000000..7d6fff9
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles/default/2023-07-08.eight.md
@@ -0,0 +1,4 @@
+---
+id: 219487f7-3390-444b-814f-7fc4dc412d6c
+title: Eight
+---
diff --git a/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-01.le-one.md b/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-01.le-one.md
new file mode 100644
index 0000000..6417a75
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-01.le-one.md
@@ -0,0 +1,5 @@
+---
+id: a356f052-06a3-4f37-8376-2f136fe973c3-french
+origin: a356f052-06a3-4f37-8376-2f136fe973c3
+title: Le One
+---
diff --git a/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-02.le-two.md b/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-02.le-two.md
new file mode 100644
index 0000000..703c90c
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-02.le-two.md
@@ -0,0 +1,5 @@
+---
+id: ca648856-ff12-407d-a523-72074f5997e1-french
+origin: ca648856-ff12-407d-a523-72074f5997e1
+title: Le Two
+---
diff --git a/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-03.le-three.md b/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-03.le-three.md
new file mode 100644
index 0000000..3edbd1f
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-03.le-three.md
@@ -0,0 +1,5 @@
+---
+id: 312dff5e-4d4e-44bd-ac47-80ef58278675-french
+origin: 312dff5e-4d4e-44bd-ac47-80ef58278675
+title: Le Three
+---
diff --git a/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-04.le-four.md b/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-04.le-four.md
new file mode 100644
index 0000000..df73ca4
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-04.le-four.md
@@ -0,0 +1,5 @@
+---
+id: d813ea6f-a637-4c6b-a724-c9e5f70e23de-french
+origin: d813ea6f-a637-4c6b-a724-c9e5f70e23de
+title: Le Four
+---
diff --git a/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-05.le-five.md b/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-05.le-five.md
new file mode 100644
index 0000000..37fbe5d
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/articles/french/2023-07-05.le-five.md
@@ -0,0 +1,5 @@
+---
+id: 3a2e2f92-f93e-481d-b120-c63ff09c1775-french
+origin: 3a2e2f92-f93e-481d-b120-c63ff09c1775
+title: Le Five
+---
diff --git a/tests/Fixtures/site-localized/content/collections/pages.yaml b/tests/Fixtures/site-localized/content/collections/pages.yaml
new file mode 100644
index 0000000..1d99167
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/pages.yaml
@@ -0,0 +1,8 @@
+title: Pages
+sites:
+ - default
+ - french
+revisions: false
+route: '{parent_uri}/{slug}'
+structure:
+ root: true
diff --git a/tests/Fixtures/site-localized/content/collections/pages/default/about.md b/tests/Fixtures/site-localized/content/collections/pages/default/about.md
new file mode 100644
index 0000000..c556171
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/pages/default/about.md
@@ -0,0 +1,7 @@
+---
+title: About
+updated_by: 96300192-873c-4615-b992-157508a8d7c5
+updated_at: 1579284102
+id: 62136fa2-9e5c-4c38-a894-a2753f02f5ff
+---
+I'm just a kid living in the 90's, writing articles in his secret public journal wonder if someday, somewhere in the future, they will be read by someone.
diff --git a/tests/Fixtures/site-localized/content/collections/pages/default/articles.md b/tests/Fixtures/site-localized/content/collections/pages/default/articles.md
new file mode 100644
index 0000000..9f07676
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/pages/default/articles.md
@@ -0,0 +1,8 @@
+---
+title: Articles
+template: articles.index
+updated_by: 96300192-873c-4615-b992-157508a8d7c5
+updated_at: 1579283552
+id: b9e4bfe3-9c12-4553-b7ef-f43c22ffaa63
+---
+These are my various writings. Some might say they are cool.
\ No newline at end of file
diff --git a/tests/Fixtures/site-localized/content/collections/pages/default/home.md b/tests/Fixtures/site-localized/content/collections/pages/default/home.md
new file mode 100644
index 0000000..9f7d027
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/pages/default/home.md
@@ -0,0 +1,8 @@
+---
+title: Home
+subtitle: 'I see pride. I see power.'
+updated_by: b6c037ad-5bcc-41a8-a455-9ab54573f689
+updated_at: 1606223924
+id: home
+---
+I see a bad-ass mother.
diff --git a/tests/Fixtures/site-localized/content/collections/pages/default/topics.md b/tests/Fixtures/site-localized/content/collections/pages/default/topics.md
new file mode 100644
index 0000000..ec52c20
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/pages/default/topics.md
@@ -0,0 +1,6 @@
+---
+title: Topics
+updated_by: ea0c21bd-9703-4bb1-9fed-58ec0e129dd7
+updated_at: 1579534416
+id: f5a53468-017e-4725-b5b6-a745df7e94cb
+---
diff --git a/tests/Fixtures/site-localized/content/collections/pages/french/le-about.md b/tests/Fixtures/site-localized/content/collections/pages/french/le-about.md
new file mode 100644
index 0000000..9ba10f6
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/pages/french/le-about.md
@@ -0,0 +1,8 @@
+---
+title: Le About
+updated_by: 96300192-873c-4615-b992-157508a8d7c5
+updated_at: 1579284102
+id: 62136fa2-9e5c-4c38-a894-a2753f02f5ff-french
+origin: 62136fa2-9e5c-4c38-a894-a2753f02f5ff
+---
+I'm just a kid living in the 90's, writing articles in his secret public journal wonder if someday, somewhere in the future, they will be read by someone.
diff --git a/tests/Fixtures/site-localized/content/collections/pages/french/le-articles.md b/tests/Fixtures/site-localized/content/collections/pages/french/le-articles.md
new file mode 100644
index 0000000..9d2cff1
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/pages/french/le-articles.md
@@ -0,0 +1,9 @@
+---
+title: Le Articles
+template: articles.index
+updated_by: 96300192-873c-4615-b992-157508a8d7c5
+updated_at: 1579283552
+id: b9e4bfe3-9c12-4553-b7ef-f43c22ffaa63-french
+origin: b9e4bfe3-9c12-4553-b7ef-f43c22ffaa63
+---
+These are my various writings. Some might say they are cool.
diff --git a/tests/Fixtures/site-localized/content/collections/pages/french/le-home.md b/tests/Fixtures/site-localized/content/collections/pages/french/le-home.md
new file mode 100644
index 0000000..4251224
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/pages/french/le-home.md
@@ -0,0 +1,9 @@
+---
+title: Le Home
+subtitle: 'I see pride. I see power.'
+updated_by: b6c037ad-5bcc-41a8-a455-9ab54573f689
+updated_at: 1606223924
+id: home-french
+origin: home
+---
+I see a bad-ass mother.
diff --git a/tests/Fixtures/site-localized/content/collections/pages/french/le-topics.md b/tests/Fixtures/site-localized/content/collections/pages/french/le-topics.md
new file mode 100644
index 0000000..00d220e
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/collections/pages/french/le-topics.md
@@ -0,0 +1,7 @@
+---
+title: Le Topics
+updated_by: ea0c21bd-9703-4bb1-9fed-58ec0e129dd7
+updated_at: 1579534416
+id: f5a53468-017e-4725-b5b6-a745df7e94cb-french
+origin: f5a53468-017e-4725-b5b6-a745df7e94cb
+---
diff --git a/tests/Fixtures/site-localized/content/trees/collections/default/pages.yaml b/tests/Fixtures/site-localized/content/trees/collections/default/pages.yaml
new file mode 100644
index 0000000..da59780
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/trees/collections/default/pages.yaml
@@ -0,0 +1,3 @@
+tree:
+ -
+ entry: home
diff --git a/tests/Fixtures/site-localized/content/trees/collections/french/pages.yaml b/tests/Fixtures/site-localized/content/trees/collections/french/pages.yaml
new file mode 100644
index 0000000..0a07f75
--- /dev/null
+++ b/tests/Fixtures/site-localized/content/trees/collections/french/pages.yaml
@@ -0,0 +1,3 @@
+tree:
+ -
+ entry: home-french
diff --git a/tests/Fixtures/site/content/collections/articles.yaml b/tests/Fixtures/site/content/collections/articles.yaml
new file mode 100644
index 0000000..3a271d0
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/articles.yaml
@@ -0,0 +1,11 @@
+title: Articles
+route: 'articles/{slug}'
+template: articles.show
+mount: b9e4bfe3-9c12-4553-b7ef-f43c22ffaa63
+taxonomies:
+ - topics
+revisions: false
+date: true
+date_behavior:
+ past: public
+ future: private
diff --git a/tests/Fixtures/site/content/collections/articles/2023-07-01.one.md b/tests/Fixtures/site/content/collections/articles/2023-07-01.one.md
new file mode 100644
index 0000000..9792983
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/articles/2023-07-01.one.md
@@ -0,0 +1,4 @@
+---
+id: a356f052-06a3-4f37-8376-2f136fe973c3
+title: One
+---
diff --git a/tests/Fixtures/site/content/collections/articles/2023-07-02.two.md b/tests/Fixtures/site/content/collections/articles/2023-07-02.two.md
new file mode 100644
index 0000000..107524b
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/articles/2023-07-02.two.md
@@ -0,0 +1,4 @@
+---
+id: ca648856-ff12-407d-a523-72074f5997e1
+title: Two
+---
diff --git a/tests/Fixtures/site/content/collections/articles/2023-07-03.three.md b/tests/Fixtures/site/content/collections/articles/2023-07-03.three.md
new file mode 100644
index 0000000..059a10f
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/articles/2023-07-03.three.md
@@ -0,0 +1,4 @@
+---
+id: 312dff5e-4d4e-44bd-ac47-80ef58278675
+title: Three
+---
diff --git a/tests/Fixtures/site/content/collections/articles/2023-07-04.four.md b/tests/Fixtures/site/content/collections/articles/2023-07-04.four.md
new file mode 100644
index 0000000..b3d4282
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/articles/2023-07-04.four.md
@@ -0,0 +1,4 @@
+---
+id: d813ea6f-a637-4c6b-a724-c9e5f70e23de
+title: Four
+---
diff --git a/tests/Fixtures/site/content/collections/articles/2023-07-05.five.md b/tests/Fixtures/site/content/collections/articles/2023-07-05.five.md
new file mode 100644
index 0000000..38d8f24
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/articles/2023-07-05.five.md
@@ -0,0 +1,4 @@
+---
+id: 3a2e2f92-f93e-481d-b120-c63ff09c1775
+title: Five
+---
diff --git a/tests/Fixtures/site/content/collections/articles/2023-07-06.six.md b/tests/Fixtures/site/content/collections/articles/2023-07-06.six.md
new file mode 100644
index 0000000..d544613
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/articles/2023-07-06.six.md
@@ -0,0 +1,4 @@
+---
+id: c72306d0-b6ae-4f3a-88eb-6c01d5a83c0d
+title: Six
+---
diff --git a/tests/Fixtures/site/content/collections/articles/2023-07-07.seven.md b/tests/Fixtures/site/content/collections/articles/2023-07-07.seven.md
new file mode 100644
index 0000000..a5c56a5
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/articles/2023-07-07.seven.md
@@ -0,0 +1,4 @@
+---
+id: 6614e8af-4c11-4790-a47e-ebb6b685851d
+title: Seven
+---
diff --git a/tests/Fixtures/site/content/collections/articles/2023-07-08.eight.md b/tests/Fixtures/site/content/collections/articles/2023-07-08.eight.md
new file mode 100644
index 0000000..7d6fff9
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/articles/2023-07-08.eight.md
@@ -0,0 +1,4 @@
+---
+id: 219487f7-3390-444b-814f-7fc4dc412d6c
+title: Eight
+---
diff --git a/tests/Fixtures/site/content/collections/pages.yaml b/tests/Fixtures/site/content/collections/pages.yaml
new file mode 100644
index 0000000..ffa599c
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/pages.yaml
@@ -0,0 +1,5 @@
+title: Pages
+revisions: false
+route: '{parent_uri}/{slug}'
+structure:
+ root: true
diff --git a/tests/Fixtures/site/content/collections/pages/about.md b/tests/Fixtures/site/content/collections/pages/about.md
new file mode 100644
index 0000000..c556171
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/pages/about.md
@@ -0,0 +1,7 @@
+---
+title: About
+updated_by: 96300192-873c-4615-b992-157508a8d7c5
+updated_at: 1579284102
+id: 62136fa2-9e5c-4c38-a894-a2753f02f5ff
+---
+I'm just a kid living in the 90's, writing articles in his secret public journal wonder if someday, somewhere in the future, they will be read by someone.
diff --git a/tests/Fixtures/site/content/collections/pages/articles.md b/tests/Fixtures/site/content/collections/pages/articles.md
new file mode 100644
index 0000000..9f07676
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/pages/articles.md
@@ -0,0 +1,8 @@
+---
+title: Articles
+template: articles.index
+updated_by: 96300192-873c-4615-b992-157508a8d7c5
+updated_at: 1579283552
+id: b9e4bfe3-9c12-4553-b7ef-f43c22ffaa63
+---
+These are my various writings. Some might say they are cool.
\ No newline at end of file
diff --git a/tests/Fixtures/site/content/collections/pages/home.md b/tests/Fixtures/site/content/collections/pages/home.md
new file mode 100644
index 0000000..9f7d027
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/pages/home.md
@@ -0,0 +1,8 @@
+---
+title: Home
+subtitle: 'I see pride. I see power.'
+updated_by: b6c037ad-5bcc-41a8-a455-9ab54573f689
+updated_at: 1606223924
+id: home
+---
+I see a bad-ass mother.
diff --git a/tests/Fixtures/site/content/collections/pages/topics.md b/tests/Fixtures/site/content/collections/pages/topics.md
new file mode 100644
index 0000000..ec52c20
--- /dev/null
+++ b/tests/Fixtures/site/content/collections/pages/topics.md
@@ -0,0 +1,6 @@
+---
+title: Topics
+updated_by: ea0c21bd-9703-4bb1-9fed-58ec0e129dd7
+updated_at: 1579534416
+id: f5a53468-017e-4725-b5b6-a745df7e94cb
+---
diff --git a/tests/Fixtures/site/content/trees/collections/pages.yaml b/tests/Fixtures/site/content/trees/collections/pages.yaml
new file mode 100644
index 0000000..da59780
--- /dev/null
+++ b/tests/Fixtures/site/content/trees/collections/pages.yaml
@@ -0,0 +1,3 @@
+tree:
+ -
+ entry: home
diff --git a/tests/GenerateTest.php b/tests/GenerateTest.php
new file mode 100644
index 0000000..1f8bd02
--- /dev/null
+++ b/tests/GenerateTest.php
@@ -0,0 +1,234 @@
+generate();
+
+ $expectedFiles = [
+ '404.html',
+ 'index.html',
+ 'about/index.html',
+ 'topics/index.html',
+ 'articles/index.html',
+ 'articles/one/index.html',
+ 'articles/two/index.html',
+ 'articles/three/index.html',
+ 'articles/four/index.html',
+ 'articles/five/index.html',
+ 'articles/six/index.html',
+ 'articles/seven/index.html',
+ 'articles/eight/index.html',
+ ];
+
+ $this->assertEqualsCanonicalizing($expectedFiles, array_keys($files));
+
+ $this->assertStringContainsString('404!
', $files['404.html']);
+
+ $this->assertStringContainsString('Page Title: Home
', $files['index.html']);
+ $this->assertStringContainsString('Page Title: About
', $files['about/index.html']);
+ $this->assertStringContainsString('Page Title: Topics
', $files['topics/index.html']);
+
+ $this->assertStringContainsString('Articles Index Page Title
', $index = $files['articles/index.html']);
+ $this->assertStringContainsString('One', $index);
+ $this->assertStringContainsString('Two', $index);
+ $this->assertStringContainsString('Three', $index);
+ $this->assertStringContainsString('Four', $index);
+ $this->assertStringContainsString('Five', $index);
+ $this->assertStringContainsString('Six', $index);
+ $this->assertStringContainsString('Seven', $index);
+ $this->assertStringContainsString('Eight', $index);
+
+ $this->assertStringContainsString('Article Title: One
', $files['articles/one/index.html']);
+ $this->assertStringContainsString('Article Title: Two
', $files['articles/two/index.html']);
+ $this->assertStringContainsString('Article Title: Three
', $files['articles/three/index.html']);
+ $this->assertStringContainsString('Article Title: Four
', $files['articles/four/index.html']);
+ $this->assertStringContainsString('Article Title: Five
', $files['articles/five/index.html']);
+ $this->assertStringContainsString('Article Title: Six
', $files['articles/six/index.html']);
+ $this->assertStringContainsString('Article Title: Seven
', $files['articles/seven/index.html']);
+ $this->assertStringContainsString('Article Title: Eight
', $files['articles/eight/index.html']);
+ }
+
+ /** @test */
+ public function it_generates_pages_to_custom_destination()
+ {
+ Config::set('statamic.ssg.destination', $this->destination = base_path('custom_export'));
+
+ $this->generate();
+
+ $this->assertFalse($this->files->exists(storage_path('app/static')));
+ $this->assertCount(13, $this->files->allFiles(base_path('custom_export')));
+
+ $this->cleanUpDestination();
+ }
+
+ /** @test */
+ public function it_generates_paginated_pages()
+ {
+ $this->files->put(resource_path('views/articles/index.antlers.html'), <<<'EOT'
+{{ collection:articles sort="date:asc" paginate="3" as="articles" }}
+ {{ articles }}
+ {{ title }}
+ {{ /articles }}
+
+ {{ paginate }}
+ Current Page: {{ current_page }}
+ Total Pages: {{ total_pages }}
+ Prev Link: {{ prev_page }}
+ Next Link: {{ next_page }}
+ {{ /paginate }}
+{{ /collection:articles }}
+EOT
+ );
+
+ $this->generate();
+
+ $files = $this->getGeneratedFilesAtPath($this->destinationPath('articles'));
+
+ $expectedArticlesFiles = [
+ 'articles/index.html',
+ 'articles/page/1/index.html',
+ 'articles/page/2/index.html',
+ 'articles/page/3/index.html',
+ 'articles/one/index.html',
+ 'articles/two/index.html',
+ 'articles/three/index.html',
+ 'articles/four/index.html',
+ 'articles/five/index.html',
+ 'articles/six/index.html',
+ 'articles/seven/index.html',
+ 'articles/eight/index.html',
+ ];
+
+ $this->assertEqualsCanonicalizing($expectedArticlesFiles, array_keys($files));
+
+ // Index assertions on implicit page 1
+ $index = $files['articles/index.html'];
+ $this->assertStringContainsStrings(['One', 'Two', 'Three'], $index);
+ $this->assertStringNotContainsStrings(['Four', 'Five', 'Six'], $index);
+ $this->assertStringNotContainsStrings(['Seven', 'Eight'], $index);
+ $this->assertStringContainsString('Current Page: 1', $index);
+ $this->assertStringContainsString('Total Pages: 3', $index);
+ $this->assertStringContainsString('Next Link: /articles/page/2', $index);
+
+ // Index assertions on explicit page 1
+ $index = $files['articles/page/1/index.html'];
+ $this->assertStringContainsStrings(['One', 'Two', 'Three'], $index);
+ $this->assertStringNotContainsStrings(['Four', 'Five', 'Six'], $index);
+ $this->assertStringNotContainsStrings(['Seven', 'Eight'], $index);
+ $this->assertStringContainsString('Current Page: 1', $index);
+ $this->assertStringContainsString('Total Pages: 3', $index);
+ $this->assertStringContainsString('Next Link: /articles/page/2', $index);
+
+ // Index assertions on page 2
+ $index = $files['articles/page/2/index.html'];
+ $this->assertStringNotContainsStrings(['One', 'Two', 'Three'], $index);
+ $this->assertStringContainsStrings(['Four', 'Five', 'Six'], $index);
+ $this->assertStringNotContainsStrings(['Seven', 'Eight'], $index);
+ $this->assertStringContainsString('Current Page: 2', $index);
+ $this->assertStringContainsString('Total Pages: 3', $index);
+ $this->assertStringContainsString('Prev Link: /articles/page/1', $index);
+ $this->assertStringContainsString('Next Link: /articles/page/3', $index);
+
+ // Index assertions on page 3
+ $index = $files['articles/page/3/index.html'];
+ $this->assertStringNotContainsStrings(['One', 'Two', 'Three'], $index);
+ $this->assertStringNotContainsStrings(['Four', 'Five', 'Six'], $index);
+ $this->assertStringContainsStrings(['Seven', 'Eight'], $index);
+ $this->assertStringContainsString('Current Page: 3', $index);
+ $this->assertStringContainsString('Total Pages: 3', $index);
+ $this->assertStringContainsString('Prev Link: /articles/page/2', $index);
+ }
+
+ /** @test */
+ public function it_generates_pagination_with_custom_page_name_and_route()
+ {
+ // Here we'll override the `pagination_route`.
+ Config::set('statamic.ssg.pagination_route', '{url}/{page_name}-{page_number}');
+
+ // And we'll also use a custom `page_name` param.
+ // This could even be passed in as a translatable string if the user wants `page` in different languages, etc.
+ $this->files->put(resource_path('views/articles/index.antlers.html'), <<<'EOT'
+{{ collection:articles sort="date:asc" paginate="3" page_name="p" as="articles" }}
+ {{ articles }}
+ {{ title }}
+ {{ /articles }}
+
+ {{ paginate }}
+ Current Page: {{ current_page }}
+ Total Pages: {{ total_pages }}
+ Prev Link: {{ prev_page }}
+ Next Link: {{ next_page }}
+ {{ /paginate }}
+{{ /collection:articles }}
+EOT
+ );
+
+ $this->generate();
+
+ $files = $this->getGeneratedFilesAtPath($this->destinationPath('articles'));
+
+ $expectedArticlesFiles = [
+ 'articles/index.html',
+ 'articles/p-1/index.html',
+ 'articles/p-2/index.html',
+ 'articles/p-3/index.html',
+ 'articles/one/index.html',
+ 'articles/two/index.html',
+ 'articles/three/index.html',
+ 'articles/four/index.html',
+ 'articles/five/index.html',
+ 'articles/six/index.html',
+ 'articles/seven/index.html',
+ 'articles/eight/index.html',
+ ];
+
+ $this->assertEqualsCanonicalizing($expectedArticlesFiles, array_keys($files));
+
+ // Index assertions on implicit page 1
+ $index = $files['articles/index.html'];
+ $this->assertStringContainsStrings(['One', 'Two', 'Three'], $index);
+ $this->assertStringNotContainsStrings(['Four', 'Five', 'Six'], $index);
+ $this->assertStringNotContainsStrings(['Seven', 'Eight'], $index);
+ $this->assertStringContainsString('Current Page: 1', $index);
+ $this->assertStringContainsString('Total Pages: 3', $index);
+ $this->assertStringContainsString('Next Link: /articles/p-2', $index);
+
+ // Index assertions on explicit page 1
+ $index = $files['articles/p-1/index.html'];
+ $this->assertStringContainsStrings(['One', 'Two', 'Three'], $index);
+ $this->assertStringNotContainsStrings(['Four', 'Five', 'Six'], $index);
+ $this->assertStringNotContainsStrings(['Seven', 'Eight'], $index);
+ $this->assertStringContainsString('Current Page: 1', $index);
+ $this->assertStringContainsString('Total Pages: 3', $index);
+ $this->assertStringContainsString('Next Link: /articles/p-2', $index);
+
+ // Index assertions on page 2
+ $index = $files['articles/p-2/index.html'];
+ $this->assertStringNotContainsStrings(['One', 'Two', 'Three'], $index);
+ $this->assertStringContainsStrings(['Four', 'Five', 'Six'], $index);
+ $this->assertStringNotContainsStrings(['Seven', 'Eight'], $index);
+ $this->assertStringContainsString('Current Page: 2', $index);
+ $this->assertStringContainsString('Total Pages: 3', $index);
+ $this->assertStringContainsString('Prev Link: /articles/p-1', $index);
+ $this->assertStringContainsString('Next Link: /articles/p-3', $index);
+
+ // Index assertions on page 3
+ $index = $files['articles/p-3/index.html'];
+ $this->assertStringNotContainsStrings(['One', 'Two', 'Three'], $index);
+ $this->assertStringNotContainsStrings(['Four', 'Five', 'Six'], $index);
+ $this->assertStringContainsStrings(['Seven', 'Eight'], $index);
+ $this->assertStringContainsString('Current Page: 3', $index);
+ $this->assertStringContainsString('Total Pages: 3', $index);
+ $this->assertStringContainsString('Prev Link: /articles/p-2', $index);
+ }
+}
diff --git a/tests/Localized/GenerateTest.php b/tests/Localized/GenerateTest.php
new file mode 100644
index 0000000..b689542
--- /dev/null
+++ b/tests/Localized/GenerateTest.php
@@ -0,0 +1,241 @@
+set('statamic.editions.pro', true);
+
+ $app['config']->set('statamic.sites.sites', [
+ 'default' => [
+ 'name' => 'English',
+ 'locale' => 'en_US',
+ 'url' => '/',
+ ],
+ 'french' => [
+ 'name' => 'French',
+ 'locale' => 'fr_FR',
+ 'url' => '/fr/',
+ ],
+ 'italian' => [
+ 'name' => 'Italian',
+ 'locale' => 'it_IT',
+ 'url' => '/it/',
+ ],
+ ]);
+ }
+
+ /** @test */
+ public function it_generates_pages_for_localized_site_fixture()
+ {
+ $files = $this->generate();
+
+ $expectedFiles = [
+ '404.html',
+ 'index.html',
+ 'about/index.html',
+ 'topics/index.html',
+ 'articles/index.html',
+ 'articles/one/index.html',
+ 'articles/two/index.html',
+ 'articles/three/index.html',
+ 'articles/four/index.html',
+ 'articles/five/index.html',
+ 'articles/six/index.html',
+ 'articles/seven/index.html',
+ 'articles/eight/index.html',
+ 'fr/index.html',
+ 'fr/le-about/index.html',
+ 'fr/le-topics/index.html',
+ 'fr/le-articles/index.html',
+ 'fr/le-articles/le-one/index.html',
+ 'fr/le-articles/le-two/index.html',
+ 'fr/le-articles/le-three/index.html',
+ 'fr/le-articles/le-four/index.html',
+ 'fr/le-articles/le-five/index.html',
+ ];
+
+ $this->assertEqualsCanonicalizing($expectedFiles, array_keys($files));
+
+ $this->assertStringContainsString('404!
', $files['404.html']);
+
+ $this->assertStringContainsString('Page Title: Home
', $files['index.html']);
+ $this->assertStringContainsString('Page Title: About
', $files['about/index.html']);
+ $this->assertStringContainsString('Page Title: Topics
', $files['topics/index.html']);
+
+ $this->assertStringContainsString('Articles Index Page Title
', $index = $files['articles/index.html']);
+ $this->assertStringContainsString('One', $index);
+ $this->assertStringContainsString('Two', $index);
+ $this->assertStringContainsString('Three', $index);
+ $this->assertStringContainsString('Four', $index);
+ $this->assertStringContainsString('Five', $index);
+ $this->assertStringContainsString('Six', $index);
+ $this->assertStringContainsString('Seven', $index);
+ $this->assertStringContainsString('Eight', $index);
+
+ $this->assertStringContainsString('Article Title: One
', $files['articles/one/index.html']);
+ $this->assertStringContainsString('Article Title: Two
', $files['articles/two/index.html']);
+ $this->assertStringContainsString('Article Title: Three
', $files['articles/three/index.html']);
+ $this->assertStringContainsString('Article Title: Four
', $files['articles/four/index.html']);
+ $this->assertStringContainsString('Article Title: Five
', $files['articles/five/index.html']);
+ $this->assertStringContainsString('Article Title: Six
', $files['articles/six/index.html']);
+ $this->assertStringContainsString('Article Title: Seven
', $files['articles/seven/index.html']);
+ $this->assertStringContainsString('Article Title: Eight
', $files['articles/eight/index.html']);
+
+ $this->assertStringContainsString('Page Title: Le Home
', $files['fr/index.html']);
+ $this->assertStringContainsString('Page Title: Le About
', $files['fr/le-about/index.html']);
+ $this->assertStringContainsString('Page Title: Le Topics
', $files['fr/le-topics/index.html']);
+
+ $this->assertStringContainsString('Articles Index Page Title
', $index = $files['fr/le-articles/index.html']);
+ $this->assertStringContainsString('Le One', $index);
+ $this->assertStringContainsString('Le Two', $index);
+ $this->assertStringContainsString('Le Three', $index);
+ $this->assertStringContainsString('Le Four', $index);
+ $this->assertStringContainsString('Le Five', $index);
+
+ $this->assertStringContainsString('Article Title: Le One
', $files['fr/le-articles/le-one/index.html']);
+ $this->assertStringContainsString('Article Title: Le Two
', $files['fr/le-articles/le-two/index.html']);
+ $this->assertStringContainsString('Article Title: Le Three
', $files['fr/le-articles/le-three/index.html']);
+ $this->assertStringContainsString('Article Title: Le Four
', $files['fr/le-articles/le-four/index.html']);
+ $this->assertStringContainsString('Article Title: Le Five
', $files['fr/le-articles/le-five/index.html']);
+ }
+
+ /** @test */
+ public function it_generates_localized_paginated_pages()
+ {
+ $this->files->put(resource_path('views/articles/index.antlers.html'), <<<'EOT'
+{{ collection:articles sort="date:asc" paginate="3" as="articles" }}
+ {{ articles }}
+ {{ title }}
+ {{ /articles }}
+
+ {{ paginate }}
+ Current Page: {{ current_page }}
+ Total Pages: {{ total_pages }}
+ Prev Link: {{ prev_page }}
+ Next Link: {{ next_page }}
+ {{ /paginate }}
+{{ /collection:articles }}
+EOT
+ );
+
+ $this->generate();
+
+ $files = $this->getGeneratedFilesAtPath($this->destinationPath('fr/le-articles'));
+
+ $expectedArticlesFiles = [
+ 'fr/le-articles/index.html',
+ 'fr/le-articles/page/1/index.html',
+ 'fr/le-articles/page/2/index.html',
+ 'fr/le-articles/le-one/index.html',
+ 'fr/le-articles/le-two/index.html',
+ 'fr/le-articles/le-three/index.html',
+ 'fr/le-articles/le-four/index.html',
+ 'fr/le-articles/le-five/index.html',
+ ];
+
+ $this->assertEqualsCanonicalizing($expectedArticlesFiles, array_keys($files));
+
+ // Index assertions on implicit page 1
+ $index = $files['fr/le-articles/index.html'];
+ $this->assertStringContainsStrings(['Le One', 'Le Two', 'Le Three'], $index);
+ $this->assertStringNotContainsStrings(['Le Four', 'Le Five'], $index);
+ $this->assertStringContainsString('Current Page: 1', $index);
+ $this->assertStringContainsString('Total Pages: 2', $index);
+ $this->assertStringContainsString('Next Link: /fr/le-articles/page/2', $index);
+
+ // Index assertions on explicit page 1
+ $index = $files['fr/le-articles/page/1/index.html'];
+ $this->assertStringContainsStrings(['Le One', 'Le Two', 'Le Three'], $index);
+ $this->assertStringNotContainsStrings(['Le Four', 'Le Five'], $index);
+ $this->assertStringContainsString('Current Page: 1', $index);
+ $this->assertStringContainsString('Total Pages: 2', $index);
+ $this->assertStringContainsString('Next Link: /fr/le-articles/page/2', $index);
+
+ // Index assertions on page 2
+ $index = $files['fr/le-articles/page/2/index.html'];
+ $this->assertStringNotContainsStrings(['Le One', 'Le Two', 'Le Three'], $index);
+ $this->assertStringContainsStrings(['Le Four', 'Le Five'], $index);
+ $this->assertStringContainsString('Current Page: 2', $index);
+ $this->assertStringContainsString('Total Pages: 2', $index);
+ $this->assertStringContainsString('Prev Link: /fr/le-articles/page/1', $index);
+ }
+
+ /** @test */
+ public function it_generates_localized_pagination_with_custom_page_name_and_route()
+ {
+ // Here we'll override the `pagination_route`.
+ Config::set('statamic.ssg.pagination_route', '{url}/{page_name}-{page_number}');
+
+ // And we'll also use a custom `page_name` param.
+ // This could even be passed in as a translatable string if the user wants `page` in different languages, etc.
+ $this->files->put(resource_path('views/articles/index.antlers.html'), <<<'EOT'
+{{ collection:articles sort="date:asc" paginate="3" page_name="p" as="articles" }}
+ {{ articles }}
+ {{ title }}
+ {{ /articles }}
+
+ {{ paginate }}
+ Current Page: {{ current_page }}
+ Total Pages: {{ total_pages }}
+ Prev Link: {{ prev_page }}
+ Next Link: {{ next_page }}
+ {{ /paginate }}
+{{ /collection:articles }}
+EOT
+ );
+
+ $this->generate();
+
+ $files = $this->getGeneratedFilesAtPath($this->destinationPath('fr/le-articles'));
+
+ $expectedArticlesFiles = [
+ 'fr/le-articles/index.html',
+ 'fr/le-articles/p-1/index.html',
+ 'fr/le-articles/p-2/index.html',
+ 'fr/le-articles/le-one/index.html',
+ 'fr/le-articles/le-two/index.html',
+ 'fr/le-articles/le-three/index.html',
+ 'fr/le-articles/le-four/index.html',
+ 'fr/le-articles/le-five/index.html',
+ ];
+
+ $this->assertEqualsCanonicalizing($expectedArticlesFiles, array_keys($files));
+
+ // Index assertions on implicit page 1
+ $index = $files['fr/le-articles/index.html'];
+ $this->assertStringContainsStrings(['Le One', 'Le Two', 'Le Three'], $index);
+ $this->assertStringNotContainsStrings(['Le Four', 'Le Five'], $index);
+ $this->assertStringContainsString('Current Page: 1', $index);
+ $this->assertStringContainsString('Total Pages: 2', $index);
+ $this->assertStringContainsString('Next Link: /fr/le-articles/p-2', $index);
+
+ // Index assertions on explicit page 1
+ $index = $files['fr/le-articles/p-1/index.html'];
+ $this->assertStringContainsStrings(['Le One', 'Le Two', 'Le Three'], $index);
+ $this->assertStringNotContainsStrings(['Le Four', 'Le Five'], $index);
+ $this->assertStringContainsString('Current Page: 1', $index);
+ $this->assertStringContainsString('Total Pages: 2', $index);
+ $this->assertStringContainsString('Next Link: /fr/le-articles/p-2', $index);
+
+ // Index assertions on page 2
+ $index = $files['fr/le-articles/p-2/index.html'];
+ $this->assertStringNotContainsStrings(['Le One', 'Le Two', 'Le Three'], $index);
+ $this->assertStringContainsStrings(['Le Four', 'Le Five'], $index);
+ $this->assertStringContainsString('Current Page: 2', $index);
+ $this->assertStringContainsString('Total Pages: 2', $index);
+ $this->assertStringContainsString('Prev Link: /fr/le-articles/p-1', $index);
+ }
+}
diff --git a/tests/RequestTest.php b/tests/RequestTest.php
index 858eb98..7cd6a8d 100644
--- a/tests/RequestTest.php
+++ b/tests/RequestTest.php
@@ -54,4 +54,18 @@ public function gets_path()
$this->assertEquals('foo', $request->path());
}
+
+ /** @test */
+ public function it_can_forget_query_param()
+ {
+ $request = new Request;
+
+ $request->merge(['page' => 2]);
+
+ $this->assertEquals(['page' => 2], $request->all());
+
+ $request->forget('page');
+
+ $this->assertEquals([], $request->all());
+ }
}
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 93552a4..ee9d431 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -2,16 +2,21 @@
namespace Tests;
+use Illuminate\Filesystem\Filesystem;
use Orchestra\Testbench\TestCase as OrchestraTestCase;
-use Statamic\Providers\StatamicServiceProvider;
use Statamic\Statamic;
class TestCase extends OrchestraTestCase
{
+ protected $fixturePath = __DIR__.'/Fixtures';
+ protected $siteFixture = 'site';
+
protected function getPackageProviders($app)
{
return [
- StatamicServiceProvider::class,
+ \Statamic\Providers\StatamicServiceProvider::class,
+ \Wilderborn\Partyline\ServiceProvider::class,
+ \Statamic\StaticSite\ServiceProvider::class,
];
}
@@ -21,4 +26,56 @@ protected function getPackageAliases($app)
'Statamic' => Statamic::class,
];
}
+
+ protected function setUp(): void
+ {
+ parent::setUp();
+
+ $this->files = app(Filesystem::class);
+
+ $this->copyDirectoryFromFixture('resources');
+ $this->copyDirectoryFromSiteFixture('content');
+
+ $this->app->instance('fork-installed', false);
+ }
+
+ protected function copyDirectoryFromFixture($directory, $site = null)
+ {
+ if (base_path($directory)) {
+ $this->files->deleteDirectory(base_path($directory));
+ }
+
+ $origin = vsprintf('%s/%s%s', [
+ $this->fixturePath,
+ $site ? "{$site}/" : '',
+ $directory,
+ ]);
+
+ $this->files->copyDirectory($origin, base_path($directory));
+ }
+
+ protected function copyDirectoryFromSiteFixture($directory)
+ {
+ $this->copyDirectoryFromFixture($directory, $this->siteFixture);
+ }
+
+ protected function resolveApplicationConfiguration($app)
+ {
+ parent::resolveApplicationConfiguration($app);
+
+ $configs = [
+ 'assets', 'cp', 'forms', 'routes', 'static_caching',
+ 'sites', 'stache', 'system', 'users',
+ ];
+
+ foreach ($configs as $config) {
+ $app['config']->set("statamic.$config", require(__DIR__."/../vendor/statamic/cms/config/{$config}.php"));
+ }
+ }
+
+ protected function getEnvironmentSetUp($app)
+ {
+ $app['config']->set('auth.providers.users.driver', 'statamic');
+ $app['config']->set('statamic.users.repository', 'file');
+ }
}