Skip to content

Commit 6d8c967

Browse files
committed
Allow to override Book class
1 parent 9f3c9d3 commit 6d8c967

20 files changed

+160
-112
lines changed

config/titelive-client.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@
1616
],
1717
],
1818
],
19+
'book_model_class' => \Code16\LaravelTiteliveClient\Models\Book::class,
1920
];

database/factories/BookFactory.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22

33
namespace Code16\LaravelTiteliveClient\Database\Factories;
44

5-
use Code16\LaravelTiteliveClient\Book;
5+
66
use Illuminate\Database\Eloquent\Factories\Factory;
77

88
class BookFactory extends Factory
99
{
10-
protected $model = Book::class;
11-
1210
private static int $VISUAL_INDEX = 0;
1311

1412
private static array $VISUALS = [
@@ -75,6 +73,11 @@ class BookFactory extends Factory
7573
'613/9782075150613',
7674
];
7775

76+
public function modelName()
77+
{
78+
return config('titelive-client.book_model_class');
79+
}
80+
7881
public function definition()
7982
{
8083
return [

src/Api/Clients/BookCache.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Code16\LaravelTiteliveClient\Api\Clients;
44

5-
use Code16\LaravelTiteliveClient\Book;
5+
use Code16\LaravelTiteliveClient\Models\Book;
66

77
interface BookCache
88
{

src/Api/Clients/BookCacheMockForDev.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Code16\LaravelTiteliveClient\Api\Clients;
44

5-
use Code16\LaravelTiteliveClient\Book;
5+
use Code16\LaravelTiteliveClient\Models\Book;
66

77
class BookCacheMockForDev implements BookCache
88
{

src/Api/Clients/BookDirectoryClient.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Code16\LaravelTiteliveClient\Api\Clients;
44

5-
use Code16\LaravelTiteliveClient\Book;
5+
use Code16\LaravelTiteliveClient\Models\Book;
66
use Illuminate\Support\Collection;
77

88
interface BookDirectoryClient

src/Api/Clients/BookDirectoryMockClientForDev.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
namespace Code16\LaravelTiteliveClient\Api\Clients;
44

5-
use Code16\LaravelTiteliveClient\Book;
5+
use Code16\LaravelTiteliveClient\Concerns\UsesBookModel;
6+
use Code16\LaravelTiteliveClient\Models\Book;
67
use Illuminate\Support\Collection;
78

89
class BookDirectoryMockClientForDev implements BookDirectoryClient
910
{
11+
use UsesBookModel;
12+
1013
private array $params = [];
1114

1215
public function getParams(): array

src/Api/Clients/RandomBasedOnRefreshDateBookCache.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use Carbon\Carbon;
66
use Code16\LaravelTiteliveClient\Api\FindBook;
7-
use Code16\LaravelTiteliveClient\Book;
7+
use Code16\LaravelTiteliveClient\Models\Book;
88

99
/**
1010
* This cache strategy is based on a simple rule:

src/Api/Clients/TiteLive/TiteLiveClient.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
use Cache;
66
use Carbon\Carbon;
77
use Code16\LaravelTiteliveClient\Api\Clients\BookDirectoryClient;
8-
use Code16\LaravelTiteliveClient\Book;
8+
use Code16\LaravelTiteliveClient\Concerns\UsesBookModel;
9+
use Code16\LaravelTiteliveClient\Models\Book;
910
use GuzzleHttp\Cookie\SetCookie;
1011
use Illuminate\Http\Client\RequestException;
1112
use Illuminate\Support\Arr;
@@ -16,6 +17,8 @@
1617

1718
class TiteLiveClient implements BookDirectoryClient
1819
{
20+
use UsesBookModel;
21+
1922
protected string $endpoint;
2023

2124
protected string $login_endpoint;
@@ -282,7 +285,7 @@ private function mapBookFromApiResult(array $book, array $edition): ?Book
282285
return null;
283286
}
284287

285-
return new Book([
288+
return static::bookModelClass()::make([
286289
'id' => $edition['gencod'],
287290
'title' => $book['titre'],
288291
'description' => $edition['resume'] ?? null,

src/Api/SuggestBooksFromAuthors.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace Code16\LaravelTiteliveClient\Api;
44

55
use Code16\LaravelTiteliveClient\Api\Clients\BookDirectoryClient;
6-
use Code16\LaravelTiteliveClient\Book;
6+
use Code16\LaravelTiteliveClient\Models\Book;
77
use Illuminate\Support\Collection;
88

99
class SuggestBooksFromAuthors extends CacheableAction

src/Api/SuggestOtherEditions.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace Code16\LaravelTiteliveClient\Api;
44

55
use Code16\LaravelTiteliveClient\Api\Clients\BookDirectoryClient;
6-
use Code16\LaravelTiteliveClient\Book;
6+
use Code16\LaravelTiteliveClient\Models\Book;
77
use Illuminate\Support\Collection;
88

99
class SuggestOtherEditions extends CacheableAction

src/Book.php

Lines changed: 5 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -2,97 +2,10 @@
22

33
namespace Code16\LaravelTiteliveClient;
44

5-
use Code16\LaravelTiteliveClient\Database\Factories\BookFactory;
6-
use Code16\LaravelTiteliveClient\Enum\BookAvailability;
7-
use Illuminate\Database\Eloquent\Casts\Attribute;
8-
use Illuminate\Database\Eloquent\Factories\HasFactory;
9-
use Illuminate\Database\Eloquent\Model;
10-
use Illuminate\Support\Str;
11-
use JsonSerializable;
12-
13-
class Book extends Model implements JsonSerializable
5+
/**
6+
* @deprecated create a Book model in project extending
7+
* @see \Code16\LaravelTiteliveClient\Models\Book & update config with `book_model_class`
8+
*/
9+
class Book extends \Code16\LaravelTiteliveClient\Models\Book
1410
{
15-
use HasFactory;
16-
17-
protected $guarded = [];
18-
19-
protected $casts = [
20-
'id' => 'string',
21-
'published_date' => 'date',
22-
'availability' => BookAvailability::class,
23-
];
24-
25-
protected static ?string $fallbackVisualUrl = null;
26-
27-
protected static function newFactory()
28-
{
29-
return new BookFactory;
30-
}
31-
32-
protected function url(): Attribute
33-
{
34-
return Attribute::make(
35-
get: fn () => route('book.show', [
36-
'id' => $this->id,
37-
'slug' => Str::slug($this->title),
38-
])
39-
);
40-
}
41-
42-
protected function shortDetails(): Attribute
43-
{
44-
return Attribute::make(
45-
get: fn () => collect([
46-
collect($this->authors)->join(', '),
47-
$this->editor,
48-
])
49-
->filter()
50-
->join('')
51-
);
52-
}
53-
54-
public function hasStock(): bool
55-
{
56-
return $this->stock > 0;
57-
}
58-
59-
public function canBeOrdered(): bool
60-
{
61-
if (config('titelive-client.shopping_closed')) {
62-
return false;
63-
}
64-
65-
return $this->availability != BookAvailability::Forthcoming
66-
&& ($this->hasStock() || $this->availability == BookAvailability::AvailableOnDemand);
67-
}
68-
69-
public function visual(string $size, ?string $fallbackUrl = null): ?string
70-
{
71-
$url = $this->visuals[$size] ?? null;
72-
73-
if (preg_match('/no_image\.png/', $url)) {
74-
return $fallbackUrl ?: static::$fallbackVisualUrl ?: asset('/img/book-placeholder.png');
75-
}
76-
77-
return $url;
78-
}
79-
80-
public static function setFallbackVisualUrl(string $url): void
81-
{
82-
static::$fallbackVisualUrl = $url;
83-
}
84-
85-
public function jsonSerialize(): array
86-
{
87-
return (new BookJsonResource($this))->jsonSerialize();
88-
}
89-
90-
public function resolveRouteBinding($value, $field = null)
91-
{
92-
if (is_array($value)) {
93-
return new static($value);
94-
}
95-
96-
return null;
97-
}
9811
}

src/BookJsonResource.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Code16\LaravelTiteliveClient;
44

5+
use Code16\LaravelTiteliveClient\Models\Book;
56
use Illuminate\Http\Resources\Json\JsonResource;
67

78
/**

src/Concerns/UsesBookModel.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Code16\LaravelTiteliveClient\Concerns;
4+
5+
use Code16\LaravelTiteliveClient\Models\Book;
6+
7+
/**
8+
* @internal
9+
*/
10+
trait UsesBookModel
11+
{
12+
/**
13+
* @return class-string<Book>
14+
*/
15+
public static function bookModelClass(): string
16+
{
17+
return config('titelive-client.book_model_class');
18+
}
19+
}

src/Models/Book.php

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
/** @noinspection LaravelUnknownEloquentFactoryInspection */
3+
4+
namespace Code16\LaravelTiteliveClient\Models;
5+
6+
use Code16\LaravelTiteliveClient\BookJsonResource;
7+
use Code16\LaravelTiteliveClient\Database\Factories\BookFactory;
8+
use Code16\LaravelTiteliveClient\Enum\BookAvailability;
9+
use Illuminate\Database\Eloquent\Casts\Attribute;
10+
use Illuminate\Database\Eloquent\Factories\HasFactory;
11+
use Illuminate\Database\Eloquent\Model;
12+
use Illuminate\Support\Str;
13+
use JsonSerializable;
14+
15+
class Book extends Model implements JsonSerializable
16+
{
17+
use HasFactory;
18+
19+
protected $guarded = [];
20+
21+
protected $casts = [
22+
'id' => 'string',
23+
'published_date' => 'date',
24+
'availability' => BookAvailability::class,
25+
];
26+
27+
protected static ?string $fallbackVisualUrl = null;
28+
29+
protected static function newFactory()
30+
{
31+
return new BookFactory;
32+
}
33+
34+
protected function url(): Attribute
35+
{
36+
return Attribute::make(
37+
get: fn () => route('book.show', [
38+
'id' => $this->id,
39+
'slug' => Str::slug($this->title),
40+
])
41+
);
42+
}
43+
44+
protected function shortDetails(): Attribute
45+
{
46+
return Attribute::make(
47+
get: fn () => collect([
48+
collect($this->authors)->join(', '),
49+
$this->editor,
50+
])
51+
->filter()
52+
->join('')
53+
);
54+
}
55+
56+
public function hasStock(): bool
57+
{
58+
return $this->stock > 0;
59+
}
60+
61+
public function canBeOrdered(): bool
62+
{
63+
if (config('titelive-client.shopping_closed')) {
64+
return false;
65+
}
66+
67+
return $this->availability != BookAvailability::Forthcoming
68+
&& ($this->hasStock() || $this->availability == BookAvailability::AvailableOnDemand);
69+
}
70+
71+
public function visual(string $size, ?string $fallbackUrl = null): ?string
72+
{
73+
$url = $this->visuals[$size] ?? null;
74+
75+
if (preg_match('/no_image\.png/', $url)) {
76+
return $fallbackUrl ?: static::$fallbackVisualUrl ?: asset('/img/book-placeholder.png');
77+
}
78+
79+
return $url;
80+
}
81+
82+
public static function setFallbackVisualUrl(string $url): void
83+
{
84+
static::$fallbackVisualUrl = $url;
85+
}
86+
87+
public function jsonSerialize(): array
88+
{
89+
return (new BookJsonResource($this))->jsonSerialize();
90+
}
91+
92+
public function resolveRouteBinding($value, $field = null)
93+
{
94+
if (is_array($value)) {
95+
return new static($value);
96+
}
97+
98+
return null;
99+
}
100+
}

src/Utils/HasBookAttribute.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44

55
use Code16\LaravelTiteliveClient\Api\Clients\BookCache;
66
use Code16\LaravelTiteliveClient\Api\Clients\TiteLive\TiteLiveBookNotFoundException;
7-
use Code16\LaravelTiteliveClient\Book;
7+
use Code16\LaravelTiteliveClient\Concerns\UsesBookModel;
88
use Illuminate\Database\Eloquent\Casts\Attribute;
99

1010
/**
1111
* @mixin \Illuminate\Database\Eloquent\Model
1212
*/
1313
trait HasBookAttribute
1414
{
15+
use UsesBookModel;
16+
1517
public function refreshBook(bool $force = false): self
1618
{
1719
try {
@@ -31,7 +33,7 @@ public function book(): Attribute
3133
{
3234
return Attribute::make(
3335
get: fn () => $this->attributes['book'] ?? null
34-
? new Book($this->fromJson($this->attributes['book']))
36+
? static::bookModelClass()::make($this->fromJson($this->attributes['book']))
3537
: null
3638
);
3739
}

0 commit comments

Comments
 (0)