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

[5.x] Add findOrNew, firstOrCreate, createOrUpdate (& related methods) methods to Entry & Term query builders #9815

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
12 changes: 12 additions & 0 deletions src/Contracts/Entries/EntryRepository.php
Expand Up @@ -2,6 +2,8 @@

namespace Statamic\Contracts\Entries;

use Closure;

interface EntryRepository
{
public function all();
Expand All @@ -16,6 +18,16 @@ public function findOrFail($id);

public function findByUri(string $uri);

public function findOrNew($id);

public function findOr($id, Closure $callback);

public function firstOrNew(array $attributes, array $values = []);

public function firstOrCreate(array $attributes, array $values = []);

public function updateOrCreate(array $attributes, array $values = []);

public function make();

public function query();
Expand Down
12 changes: 12 additions & 0 deletions src/Contracts/Taxonomies/TermRepository.php
Expand Up @@ -2,6 +2,8 @@

namespace Statamic\Contracts\Taxonomies;

use Closure;

interface TermRepository
{
public function all();
Expand All @@ -16,6 +18,16 @@ public function findByUri(string $uri);

public function findOrFail($id);

public function findOrNew($id);

public function findOr($id, Closure $callback);

public function firstOrNew(array $attributes, array $values = []);

public function firstOrCreate(array $attributes, array $values = []);

public function updateOrCreate(array $attributes, array $values = []);

public function make(?string $slug = null);

public function query();
Expand Down
3 changes: 3 additions & 0 deletions src/Facades/Entry.php
Expand Up @@ -13,6 +13,9 @@
* @method static \Statamic\Contracts\Entries\Entry findOrFail($id)
* @method static null|\Statamic\Contracts\Entries\Entry findByUri(string $uri, string $site)
* @method static \Statamic\Contracts\Entries\Entry make()
* @method static \Statamic\Contracts\Entries\Entry firstOrNew(array $attributes, array $values)
* @method static \Statamic\Contracts\Entries\Entry firstOrCreate(array $attributes, array $values)
* @method static \Statamic\Contracts\Entries\Entry updateOrCreate(array $attributes, array $values)
* @method static \Statamic\Contracts\Entries\QueryBuilder query()
* @method static void save($entry)
* @method static void delete($entry)
Expand Down
3 changes: 3 additions & 0 deletions src/Facades/Term.php
Expand Up @@ -18,6 +18,9 @@
* @method static delete($term)
* @method static TermQueryBuilder query()
* @method static TermContract make(string $slug = null)
* @method static TermContract firstOrNew(array $attributes, array $values)
* @method static TermContract firstOrCreate(array $attributes, array $values)
* @method static TermContract updateOrCreate(array $attributes, array $values)
* @method static int entriesCount(Term $term)
*
* @see \Statamic\Contracts\Taxonomies\TermRepository
Expand Down
68 changes: 68 additions & 0 deletions src/Stache/Query/EntryQueryBuilder.php
Expand Up @@ -2,11 +2,13 @@

namespace Statamic\Stache\Query;

use Closure;
use Statamic\Contracts\Entries\QueryBuilder;
use Statamic\Entries\EntryCollection;
use Statamic\Facades;
use Statamic\Facades\Blink;
use Statamic\Facades\Collection;
use Statamic\Facades\Entry;
use Statamic\Support\Arr;

class EntryQueryBuilder extends Builder implements QueryBuilder
Expand Down Expand Up @@ -258,4 +260,70 @@ public function prepareForFakeQuery(): array

return $data;
}

public function findOrNew($id)
{
if (! is_null($entry = $this->find($id))) {
return $entry;
}

return Entry::make();
}

public function findOr($id, Closure $callback)
{
if (! is_null($entry = $this->find($id))) {
return $entry;
}

return $callback();
}

public function firstOrNew(array $attributes = [], array $values = [])
{
if (! is_null($instance = $this->where($attributes)->first())) {
return $instance;
}

$data = array_merge($attributes, $values);

if (($this->collections && count($this->collections) > 1) && ! isset($data['collection'])) {
throw new \Exception('Please specify a collection.');
}

return Entry::make()
->collection($this->collections[0] ?? $data['collection'])
->slug($data['slug'] ?? (isset($data['title']) ? Str::slug($data['title']) : null))
->data(Arr::except($data, ['collection', 'slug']));
}

public function firstOrCreate(array $attributes = [], array $values = [])
{
$entry = $this->firstOrNew($attributes, $values);

// When the entry is dirty, it means it's new and should be saved.
if ($entry->isDirty()) {
$entry->save();
}

return $entry;
}

public function updateOrCreate(array $attributes, array $values = [])
{
$entry = $this->firstOrNew($attributes, $values);

// When the entry is clean, it means it's existing and should be updated.
if ($entry->isClean()) {
if ($slug = Arr::get($values, 'slug')) {
$entry->slug($slug);
}

$entry->merge(Arr::except($values, ['slug']));
}

$entry->save();

return $entry;
}
}
70 changes: 70 additions & 0 deletions src/Stache/Query/TermQueryBuilder.php
Expand Up @@ -2,9 +2,13 @@

namespace Statamic\Stache\Query;

use Closure;
use Statamic\Facades;
use Statamic\Facades\Collection;
use Statamic\Facades\Term;
use Statamic\Support\Arr;
use Statamic\Support\Str;
use Statamic\Taxonomies\LocalizedTerm;
use Statamic\Taxonomies\TermCollection;

class TermQueryBuilder extends Builder
Expand Down Expand Up @@ -202,4 +206,70 @@ public function prepareForFakeQuery(): array

return $data;
}

public function findOrNew($id)
{
if (! is_null($term = $this->find($id))) {
return $term;
}

return Term::make();
}

public function findOr($id, Closure $callback)
{
if (! is_null($term = $this->find($id))) {
return $term;
}

return $callback();
}

public function firstOrNew(array $attributes = [], array $values = [])
{
if (! is_null($instance = $this->where($attributes)->first())) {
return $instance;
}

$data = array_merge($attributes, $values);

if (($this->taxonomies && count($this->taxonomies) > 1) && ! isset($data['taxonomy'])) {
throw new \Exception('Please specify a taxonomy.');
}

return Term::make()
->taxonomy($this->taxonomies[0] ?? $data['taxonomy'])
->slug($data['slug'] ?? (isset($data['title']) ? Str::slug($data['title']) : null))
->data(Arr::except($data, ['taxonomy', 'slug']));
}

public function firstOrCreate(array $attributes = [], array $values = [])
{
$term = $this->firstOrNew($attributes, $values);

// When the term is not a LocalizedTerm, it means it's newe and should be saved.
if (! $term instanceof LocalizedTerm) {
$term->save();
}

return $term;
}

public function updateOrCreate(array $attributes, array $values = [])
{
$term = $this->firstOrNew($attributes, $values);

// When the term is a LocalizedTerm, it means it's existing and should be updated.
if ($term instanceof LocalizedTerm) {
if ($slug = Arr::get($values, 'slug')) {
$term->slug($slug);
}

$term->merge($values);
}

$term->save();

return $term;
}
}
26 changes: 26 additions & 0 deletions src/Stache/Repositories/EntryRepository.php
Expand Up @@ -2,6 +2,7 @@

namespace Statamic\Stache\Repositories;

use Closure;
use Statamic\Contracts\Entries\Entry;
use Statamic\Contracts\Entries\EntryRepository as RepositoryContract;
use Statamic\Contracts\Entries\QueryBuilder;
Expand Down Expand Up @@ -93,6 +94,31 @@ public function findByUri(string $uri, ?string $site = null): ?Entry
: $entry;
}

public function findOrNew($id)
{
return $this->query()->findOrNew($id);
}

public function findOr($id, Closure $callback)
{
return $this->query()->findOr($id, $callback);
}

public function firstOrNew(array $attributes = [], array $values = [])
{
return $this->query()->firstOrNew($attributes, $values);
}

public function firstOrCreate(array $attributes, array $values = [])
{
return $this->query()->firstOrCreate($attributes, $values);
}

public function updateOrCreate(array $attributes, array $values = [])
{
return $this->query()->updateOrCreate($attributes, $values);
}

public function save($entry)
{
if (! $entry->id()) {
Expand Down
26 changes: 26 additions & 0 deletions src/Stache/Repositories/TermRepository.php
Expand Up @@ -2,6 +2,7 @@

namespace Statamic\Stache\Repositories;

use Closure;
use Statamic\Contracts\Taxonomies\Term;
use Statamic\Contracts\Taxonomies\TermRepository as RepositoryContract;
use Statamic\Exceptions\TaxonomyNotFoundException;
Expand Down Expand Up @@ -112,6 +113,31 @@ public function findOrFail($id): Term
return $term;
}

public function findOrNew($id)
{
return $this->query()->findOrNew($id);
}

public function findOr($id, Closure $callback)
{
return $this->query()->findOr($id, $callback);
}

public function firstOrNew(array $attributes, array $values = [])
{
return $this->query()->firstOrNew($attributes, $values);
}

public function firstOrCreate(array $attributes, array $values = [])
{
return $this->query()->firstOrCreate($attributes, $values);
}

public function updateOrCreate(array $attributes, array $values = [])
{
return $this->query()->updateOrCreate($attributes, $values);
}

public function save($term)
{
$this->store
Expand Down