Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add method to find a models version at a specific time #43

Merged
merged 1 commit into from Oct 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 10 additions & 6 deletions README.md
Expand Up @@ -72,7 +72,7 @@ class Post extends Model
* @var array
*/
protected $versionable = ['title', 'content'];

// Or use blacklist
//protected $dontVersionable = ['created_at', 'updated_at'];

Expand All @@ -93,11 +93,15 @@ $post->update(['title' => 'version2']);
$post->versions; // all versions
$post->latestVersion; // latest version
// or
$post->lastVersion;
$post->lastVersion;

$post->versions->first(); // first version
// or
// or
$post->firstVersion;

$post->versionAt('2022-10-06 12:00:00'); // get version from a specific time
// or
$post->versionAt(\Carbon\Carbon::create(2022, 10, 6, 12));
```

### Reversion
Expand Down Expand Up @@ -164,8 +168,8 @@ You can set the following different version policies through property `protected
### Show diff between two versions

```php
$diff = $post->getVersion(1)->diff($post->getVersion(2));
```
$diff = $post->getVersion(1)->diff($post->getVersion(2));
```

`$diff` is a object `Overtrue\LaravelVersionable\Diff`, it based on [jfcherng/php-diff](https://github.com/jfcherng/php-diff).

Expand Down Expand Up @@ -211,7 +215,7 @@ toSideBySideHtml(array $differOptions = [], array $renderOptions = []): array
```

> **Note**
>
>
> `$differOptions` and `$renderOptions` are optional, you can set them following the README of [jfcherng/php-diff](https://github.com/jfcherng/php-diff#example).

## :heart: Sponsor me
Expand Down
20 changes: 20 additions & 0 deletions src/Versionable.php
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Support\Carbon;

trait Versionable
{
Expand Down Expand Up @@ -64,6 +65,25 @@ public function firstVersion(): MorphOne
return $this->morphOne($this->getVersionModel(), 'versionable')->oldest('id');
}

/**
* Get the version for a specific time.
*
* @param string|DateTimeInterface|null $time
* @param DateTimeZone|string|null $tz
*
* @throws \Carbon\Exceptions\InvalidFormatException
*
* @return static
*/
public function versionAt($time = null, $tz = null): ?Version
{
return $this->versions()
->where('created_at', '<=', Carbon::parse($time, $tz))
->orderByDesc('created_at')
->orderByDesc($this->getKey())
->first();
}

public function getVersion(int $id): ?Version
{
return $this->versions()->find($id);
Expand Down
79 changes: 79 additions & 0 deletions tests/VersionAtTest.php
@@ -0,0 +1,79 @@
<?php

namespace Tests;

use Illuminate\Support\Carbon;
use Overtrue\LaravelVersionable\Diff;

class VersionAtTest extends TestCase
{
protected $user;

protected function setUp(): void
{
parent::setUp();

Post::enableVersioning();

config([
'auth.providers.users.model' => User::class,
'versionable.user_model' => User::class,
]);

$this->user = User::create(['name' => 'marijoo']);
$this->actingAs($this->user);
}

/**
* @test
*/
public function it_can_find_version_at_specific_time()
{
$this->travelTo(Carbon::create(2022, 10, 1, 12, 0));

$post = Post::create(['title' => 'version1', 'content' => 'version1 content']);

$this->travelTo(Carbon::create(2022, 10, 2, 14, 0));

$post->update(['title' => 'version2']);

$this->travelTo(Carbon::create(2022, 10, 3, 10, 0));

$post->update(['title' => 'version3']);

$this->assertEquals('version1', $post->versionAt('2022-10-02 10:00:00')->contents['title']);
$this->assertEquals('version1', $post->versionAt('2022-10-02 13:59:59')->contents['title']);
$this->assertEquals('version2', $post->versionAt(Carbon::create(2022, 10, 02, 14))->contents['title']);
$this->assertEquals('version2', $post->versionAt('2022-10-02 15:00:00')->contents['title']);
$this->assertEquals('version3', $post->versionAt('2022-10-03 10:00:00')->contents['title']);
}

/**
* @test
*/
public function it_returns_null_if_given_time_is_before_first_version()
{
$this->travelTo(Carbon::create(2022, 10, 1, 12, 0));

$post = Post::create(['title' => 'version1', 'content' => 'version1 content']);

$this->assertNull($post->versionAt('2022-10-01 11:59:59'));
$this->assertEquals('version1', $post->versionAt('2022-10-01 12:00:00')->contents['title']);
}

/**
* @test
*/
public function it_returns_latest_version_if_given_time_is_in_future()
{
$this->travelTo(Carbon::create(2022, 10, 1, 12, 0));

$post = Post::create(['title' => 'version1', 'content' => 'version1 content']);

$this->travelTo(Carbon::create(2022, 10, 2, 14, 0));

$post->update(['title' => 'version2']);

$this->assertEquals('version2', $post->versionAt('2024-11-01 12:00:00')->contents['title']);
}
}