Skip to content
Closed
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
14 changes: 14 additions & 0 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,20 @@ Reports will stick around until deleted, so you are free to compare reports to s

You may generate a report through the Control Panel, or by running `php please seo-pro:generate-report`.

### Storage

By default, reports are stored as YAML files in the `storage/statamic/seopro/reports` directory. Where the filesystem is not shared between processes or does not survive a deploy - containers, serverless platforms, autoscaled instances - a report written by one process is never seen by the next request, and generating one ends on a 404. Point reports at a filesystem disk instead:

```php
// config/statamic/seo-pro.php

'reports' => [
'disk' => 's3',
],
```

The disk is any disk from `config/filesystems.php`; reports are stored under `statamic/seopro/reports` on it. Reports generated before the switch stay on the local disk and are not listed until they are copied over.

### Queuing Reports

Depending on the size of your site, generating a report may take a while. To prevent request timeouts, you may enable queues, and the reports will be truly queued in the background.
Expand Down
1 change: 1 addition & 0 deletions config/seo-pro.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
],

'reports' => [
'disk' => null,
'keep_recent' => 'all',
'queue_chunk_size' => 1000,
'title_length' => [
Expand Down
6 changes: 3 additions & 3 deletions src/Reporting/Chunk.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ protected function yamlPath()

public function save()
{
File::put($this->yamlPath(), YAML::dump([
File::disk(Report::disk())->put($this->yamlPath(), YAML::dump([
'ids' => $this->contentIds,
]));

Expand All @@ -61,7 +61,7 @@ protected function generate($ids)
$this->createPage($content[$id] ?? Data::find($id))?->save();
}

File::delete($this->folderPath());
File::disk(Report::disk())->delete($this->folderPath());

if ($this->wasLastChunk()) {
$this->report->finalize();
Expand All @@ -70,7 +70,7 @@ protected function generate($ids)

protected function wasLastChunk()
{
return File::getFolders($this->report->chunksFolder())->isEmpty();
return File::disk(Report::disk())->getFolders($this->report->chunksFolder())->isEmpty();
}

protected function createPage($content)
Expand Down
6 changes: 3 additions & 3 deletions src/Reporting/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,17 +146,17 @@ public function save()
'results' => $this->results,
];

File::put($this->path(), YAML::dump($data));
File::disk(Report::disk())->put($this->path(), YAML::dump($data));
}

protected function path()
{
$key = md5($this->id);
$parts = array_slice(str_split($key, 2), 0, 2);

return storage_path(vsprintf('statamic/seopro/reports/%s/pages/%s/%s.yaml', [
return vsprintf('statamic/seopro/reports/%s/pages/%s/%s.yaml', [
$this->report->id(), implode('/', $parts), $key,
]));
]);
}

public function model()
Expand Down
59 changes: 30 additions & 29 deletions src/Reporting/Report.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
use Statamic\Facades\Entry;
use Statamic\Facades\File;
use Statamic\Facades\Folder;
use Statamic\Facades\Term;
use Statamic\Facades\YAML;

Expand Down Expand Up @@ -112,8 +112,8 @@ public function generate()

protected function hasRemainingChunks()
{
return File::exists($this->chunksFolder())
&& File::getFolders($this->chunksFolder())->isNotEmpty();
return File::disk(static::disk())->exists($this->chunksFolder())
&& File::disk(static::disk())->getFolders($this->chunksFolder())->isNotEmpty();
}

protected function chunks()
Expand All @@ -139,8 +139,8 @@ protected function chunks()

public function finalize()
{
if (File::exists($dir = $this->chunksFolder())) {
File::delete($dir);
if (File::disk(static::disk())->exists($dir = $this->chunksFolder())) {
File::disk(static::disk())->delete($dir);
}

$this
Expand Down Expand Up @@ -284,12 +284,12 @@ public function withPages($preferCache = false)
return $this;
}

$dir = storage_path(sprintf('statamic/seopro/reports/%s/pages', $this->id));
$dir = sprintf('statamic/seopro/reports/%s/pages', $this->id);

$files = Folder::getFilesRecursively($dir);
$files = File::disk(static::disk())->getFilesRecursively($dir);

$this->pages = collect($files)
->map(fn ($file) => YAML::parse(File::get($file)))
->map(fn ($file) => YAML::parse(File::disk(static::disk())->get($file)))
->map(fn ($yaml) => (new Page($yaml['id'], $yaml['data'], $this))->setResults($yaml['results']))
->sortBy
->url()
Expand Down Expand Up @@ -326,7 +326,7 @@ public function generateIfNecessary(): self

public static function all()
{
$folders = collect(Folder::getFolders(static::preparePath()));
$folders = collect(File::disk(static::disk())->getFolders('statamic/seopro/reports'));

if ($folders->isEmpty()) {
return $folders;
Expand Down Expand Up @@ -369,7 +369,7 @@ public function fresh()

public function save()
{
File::put($this->path(), YAML::dump($this->raw = [
File::disk(static::disk())->put($this->path(), YAML::dump($this->raw = [
'date' => $this->date ?? now()->timestamp,
'status' => $this->status(),
'score' => $this->score(),
Expand All @@ -385,34 +385,46 @@ public function save()

public function delete()
{
File::delete($this->parentFolder());
File::disk(static::disk())->delete($this->parentFolder());

return $this->clearCaches();
}

/**
* The disk for File::disk(): the one configured in `reports.disk`, or else the local
* storage directory. Reports live under statamic/seopro/reports on it.
*/
public static function disk()
{
return config('statamic.seo-pro.reports.disk') ?: Storage::build([
'driver' => 'local',
'root' => storage_path(),
]);
}

public function parentFolder()
{
return storage_path('statamic/seopro/reports/'.$this->id);
return 'statamic/seopro/reports/'.$this->id;
}

public function chunksFolder()
{
return storage_path('statamic/seopro/reports/'.$this->id.'/chunks');
return 'statamic/seopro/reports/'.$this->id.'/chunks';
}

public function path()
{
return storage_path('statamic/seopro/reports/'.$this->id.'/report.yaml');
return 'statamic/seopro/reports/'.$this->id.'/report.yaml';
}

public function exists()
{
return File::exists($this->path());
return File::disk(static::disk())->exists($this->path());
}

public function load()
{
$this->raw = YAML::parse(File::get($this->path()));
$this->raw = YAML::parse(File::disk(static::disk())->get($this->path()));

$this->date = $this->raw['date'];
$this->results = $this->raw['results'];
Expand Down Expand Up @@ -499,17 +511,6 @@ protected function generateScore()
return $this;
}

public static function preparePath($path = null)
{
$path = collect([storage_path('statamic/seopro/reports'), $path])->filter()->implode('/');

if (! File::exists($path)) {
File::makeDirectory($path, 0755, true);
}

return $path;
}

protected function allContent()
{
$content = collect()
Expand Down Expand Up @@ -562,7 +563,7 @@ public static function deleteOldReports()
return false;
}

$reports = collect(app('files')->directories(storage_path('statamic/seopro/reports')));
$reports = collect(File::disk(static::disk())->getFolders('statamic/seopro/reports'));

$keepReports = $reports
->keyBy(fn ($path) => pathinfo($path)['basename'])
Expand All @@ -571,7 +572,7 @@ public static function deleteOldReports()

$reports
->reject(fn ($path) => $keepReports->contains($path))
->each(fn ($path) => app('files')->deleteDirectory($path));
->each(fn ($path) => File::disk(static::disk())->delete($path));

return true;
}
Expand Down
27 changes: 27 additions & 0 deletions tests/ReportTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Tests;

use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Storage;
use PHPUnit\Framework\Attributes\Test;
use Statamic\Facades\Blink;
use Statamic\Facades\Config;
Expand Down Expand Up @@ -68,6 +69,32 @@ public function it_increments_report_folder_numbers()
$this->assertFileExists($this->reportsPath('3'));
}

#[Test]
public function it_stores_reports_on_the_configured_disk()
{
config(['statamic.seo-pro.reports.disk' => 'reports']);
Storage::fake('reports');

$this->generateEntries(3);

Report::create()->save()->generate();

Storage::disk('reports')->assertExists('statamic/seopro/reports/1/report.yaml');
$this->assertCount(3, Storage::disk('reports')->allFiles('statamic/seopro/reports/1/pages'));
$this->assertCount(0, Storage::disk('reports')->directories('statamic/seopro/reports/1/chunks'));
$this->assertFileDoesNotExist($this->reportsPath());

$this->assertCount(1, Report::all());
$this->assertSame(1, Report::find(1)->id());
$this->assertSame(3, Report::find(1)->withPages()->pagesCrawled());
$this->assertSame(2, Report::nextId());

Report::find(1)->delete();

Storage::disk('reports')->assertMissing('statamic/seopro/reports/1/report.yaml');
$this->assertCount(0, Report::all());
}

#[Test]
public function it_can_generate_a_report()
{
Expand Down
Loading