Skip to content

Instantly share code, notes, and snippets.

@alnutile
Created November 20, 2022 11:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alnutile/aa070bb3c45d0d2a968a5752db5b18e7 to your computer and use it in GitHub Desktop.
Save alnutile/aa070bb3c45d0d2a968a5752db5b18e7 to your computer and use it in GitHub Desktop.
<?php
namespace App\Services;
use Spatie\Tags\Tag;
use Ramsey\Uuid\Uuid;
use App\Models\Recall;
use App\Tagging\Subscribables;
use Illuminate\Database\Eloquent\Model;
use Google\Cloud\Firestore\FirestoreClient;
/**
* @see https://github.com/GoogleCloudPlatform/php-docs-samples/tree/master/firestore/src
*/
class FirestoreService
{
public $collection = "recalls";
public $model = "\App\Models\Recall";
public FirestoreClient $client;
public function __construct(FirestoreClient $client)
{
$this->client = $client;
}
public function getClient()
{
return $this->client;
}
public function repopulateCollection()
{
$this->deleteAllFromCollection($this->collection);
$this->batchUpdate($this->model::all());
}
public function deleteAllFromCollection($collection)
{
$collectionReference = $this->client->collection($collection);
$documents = $collectionReference->limit(100)->documents();
while (!$documents->isEmpty()) {
$batch = $this->client->batch();
foreach ($documents as $document) {
$batch->delete($document->reference());
}
$batch->commit();
$documents = $collectionReference->limit(100)->documents();
}
}
public function updateLatest()
{
$collection = $this->client->collection($this->collection);
$documents = $collection->orderBy("id", "descending")->limit(1)->documents();
foreach ($documents as $doc) {
$recalls = $this->model::where("id", ">", $doc['id'])->get();
if (!empty($recalls)) {
$this->batchUpdate($recalls);
}
}
}
protected function batchUpdate($models)
{
$batch = $this->client->batch();
foreach ($models as $item) {
$doc = $this->client->collection($this->collection)->document(
Uuid::uuid4()->toString()
);
$reported = $item->date_reported->format("Y-m-d");
//@TODO this needs to be more dynamic
$batch->set(
$doc,
[
"id" => $item->id,
"title" => $item->title,
"body" => $item->body,
"date_reported" => $reported,
"find_out_more" => $item->find_out_more,
"country" => $item->country,
"level" => $item->level,
"source_id" => $item->source_id
]
);
}
$batch->commit();
}
}
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Facades\App\FirestoreSync\SuscribableSync;
class ResetSuscribablesOnFirebase extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'totalrecalls:reset-subscribables';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This will DELETE and reset them all!!!';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
if ($this->confirm("This will DELETE all of the recalls and then set them up again")) {
SuscribableSync::repopulateCollection();
}
return 0;
}
}
<?php
namespace App\FirestoreSync;
use App\Models\Tag;
use Ramsey\Uuid\Uuid;
use App\Tagging\Subscribables;
use App\Services\FirestoreService;
class SuscribableSync extends FirestoreService
{
public $collection = "subscribables";
public $model = "\App\Models\Tag";
public function updateLatest()
{
$collection = $this->client->collection($this->collection);
$documents = $collection->orderBy("id", "descending")->limit(1)->documents();
foreach ($documents as $doc) {
$recalls = $this->model::where("id", ">", $doc['id'])->get();
if ($recalls) {
$this->batchUpdate($recalls);
}
}
}
public function repopulateCollection()
{
$this->deleteAllFromCollection($this->collection);
$types = Subscribables::OPTIONS;
$tags = $this->model::select("id", "tag_name")
->whereIn('type', $types)
->orWhere('type', null)
->orderBy("tag_name")
->get();
$this->batchUpdate($tags);
}
protected function batchUpdate($models)
{
$batch = $this->client->batch();
foreach ($models as $item) {
$doc = $this->client->collection($this->collection)->document(
Uuid::uuid4()->toString()
);
//@TODO this needs to be more dynamic
$batch->set(
$doc,
[
"id" => $item->id,
"name" => $item->tag_name
]
);
}
$batch->commit();
}
}
<?php
namespace Tests\Feature;
use App\Models\Tag;
use Facades\App\FirestoreSync\SuscribableSync;
use Google\Cloud\Firestore\FirestoreClient;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Mockery\MockInterface;
use Tests\TestCase;
class SuscribableSyncTest extends TestCase
{
use RefreshDatabase;
public function test_sends_subscribables()
{
//make the migration and uuid test
//then make my existing work more flexible
Tag::findOrCreate(['name' => "Foo1", 'type' => "country"]);
Tag::findOrCreate(['name' => "Foo2", 'type' => "country"]);
$this->mock(FirestoreClient::class, function (MockInterface $mock) {
$mock->shouldReceive("collection")->times(13)->andReturnSelf();
$mock->shouldReceive("collection->document")->andReturnSelf();
$mock->shouldReceive("limit->documents")->andReturn(
new \Tests\Documents()
);
$mock->shouldReceive("batch")->andReturnSelf();
$mock->shouldReceive("set")->andReturnSelf();
$mock->shouldReceive("batch->commit");
});
SuscribableSync::repopulateCollection();
}
public function test_can_update_latest() {
Tag::findOrCreate(['name' => "Foo1", 'type' => "country"]);
Tag::findOrCreate(['name' => "Foo2", 'type' => "country"]);
$tag2 = Tag::latest()->first();
$this->mock(FirestoreClient::class, function(MockInterface $mock) use ($tag2) {
$mock->shouldReceive("collection")->andReturnSelf();
$mock->shouldReceive("orderBy->limit->documents")->andReturn(
[
[
'id' => $tag2->id
]
]
);
$mock->shouldReceive("batch")->andReturnSelf();
$mock->shouldReceive("collection->document")->andReturnSelf();
$mock->shouldReceive("set")->andReturnSelf();
$mock->shouldReceive("batch->commit");
});
SuscribableSync::updateLatest();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment