PHP code example of inly / core-web

1. Go to this page and download the library: Download inly/core-web library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

inly / core-web example snippets




return [
    'features' => ['snapshots' => true],
];

use Inly\CoreWeb\Client\CoreClient;
use Inly\CoreWeb\Snapshots\Snapshot;
use Inly\CoreWeb\Snapshots\SnapshotRegistry;
use Inly\CoreWeb\StaticCaching\SiteCache;

$this->app->extend(SnapshotRegistry::class, fn (SnapshotRegistry $registry) => $registry
    ->register(
        Snapshot::make('locations')
            ->version(3)                                   // bump when the stored document shape changes
            ->ttl(fresh: 3600, stale: 2592000, retry: 60)
            ->pull(fn () => LocationSnapshot::pull(CoreClient::fromConfig()))          // every document, keyed by id
            ->pullOne(fn (string $id) => LocationSnapshot::pullOne(CoreClient::fromConfig(), $id)) // one object, [] when gone
            ->partitionBy(fn (array $doc) => $doc['site'] ?? null, ['default', 'second'])
            ->emptyWhen(fn (array $documents) => $documents === [])
            ->onChange(SiteCache::flushOnChange())         // flush the partition's site
            ->sitemap(fn (array $doc, string $site) => [['loc' => '/locations/'.$doc['slug'], 'lastmod' => $doc['updated_at']]]),
        pings: ['location', 'locations'],                 // Core's ping types that refresh it
    )
    ->register($catalog, pings: ['product', 'products'], wholePings: ['product-category'])
    ->register($stock, pings: ['stock'], warm: fn (Command $command) => 0, job: fn (string $id, string $action) => new RefreshStockJob($id, $action))
    ->idle(['product-categories']));                      // accepted, acted on by nothing

$read = app(SnapshotStore::class)->read($snapshot, 'second');
$read->documents;  // keyed by id
$read->stale;      // the last good copy, served because no fresh one is cached
$read->degraded;   // nothing cached and no pull succeeded: documents are empty

->onChange(function (?string $partition, array $documents, ?SnapshotChange $change): void {
    foreach ($change?->ids() ?? array_keys($documents) as $id) { /* … */ }
})

Snapshot::make('locations')
    // ...
    ->pages(fn (array $doc, string $site) => '/locations/'.$doc['slug']);

Route::get('locations/{slug}', function (Request $request, string $slug) {
    $pages = SnapshotPage::for('locations');                 // the current site; for('locations', 'second') for another
    $location = $pages->find(fn (array $doc) => $doc['slug'] === $slug || in_array($slug, $doc['old_slugs'], true));

    return $pages->canonical($request, $location)              // 301 to its own path, or null
        ?? $pages->render('locations.show', ['location' => $location, 'title' => $location['name']], Entry::findByUri('/locations'));
});

Snapshot::make('staff')
    // ...
    ->listing(
        title: fn (array $doc, string $id) => $doc['name'],
        coreType: 'employee',                         // Core's lookup key; no link without it
        coreId: fn (array $doc, string $id) => $doc['core_id'] ?? null, // Core's primary key; defaults to the document id
    );

// config/statamic/cp.php
'widgets' => [
    ['type' => 'core_snapshot', 'snapshot' => 'staff', 'per_page' => 10, 'width' => 50],
],

Snapshot::make('campaigns')
    ->dependents(fn (array $doc, string $id, ?string $partition) => [
        $doc['url_path'],             // its own page
        '/campaigns',                 // the listing
        '/brands/'.$doc['brand'],     // its brand's page
        ...$pickedBy($id),            // pages whose content picks it
    ])
    ->onChange(SiteCache::flushOnChange());

return [
    'features' => ['chat' => true],
    'chat' => ['agents' => ['assistant' => App\Chat\AssistantContext::class]],
];

use Illuminate\Http\Request;
use Inly\CoreWeb\Chat\ChatContext;

class AssistantContext implements ChatContext
{
    public function context(?string $subject, Request $request): array
    {
        $record = $this->record($subject);

        return $record === null ? [] : ['record_id' => $record->core_id, 'page' => $record->url()];
    }

    // A different key starts a fresh conversation: one per record.
    public function key(?string $subject, Request $request): string
    {
        return (string) ($this->record($subject)?->getKey() ?? 'general');
    }

    // Only a record that exists names a conversation, so a visitor cannot mint subjects.
    private function record(?string $subject): ?Record
    {
        return $subject === null ? null : (Record::find($subject) ?? abort(404));
    }
}

use Inly\CoreWeb\Live\LiveRead;
use Inly\CoreWeb\Live\LiveRequest;

class LoanQuote extends LiveRead
{
    public function public(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return ['item' => ['json, array $input): ?array
    {
        return ['monthly' => $json['data']['monthly'] ?? null];
    }

    public function ttl(): int
    {
        return 60;
    }
}

return [
    'features' => ['live' => true],
    'live' => ['reads' => ['loan-quote' => App\Live\LoanQuote::class]],
];

$result = app(Inly\CoreWeb\Live\CoreLive::class)->read('loan-quote', ['item' => $id, 'months' => $months]);

$result->successful(); // $result->data, or $result->status and $result->errors

// config/core-web.php
return [
    'features' => ['snapshots' => true, 'forms' => true],
    'forms' => ['classes' => [App\Livewire\DamageInspection::class]],
];

use Inly\CoreWeb\Forms\CoreForm;

class DamageInspection extends CoreForm
{
    // The key of the Core form it posts to.
    public static function coreForm(): string
    {
        return 'damage-inspection';
    }

    // The Core fields the view renders.
    public static function renders(): array
    {
        return ['plate', 'name', 'email', 'photos', 'damage'];
    }

    protected function fieldsView(): string
    {
        return 'livewire.damage-inspection';
    }
}

'media' => [
    'bucket' => [
        'endpoint' => 'https://ams3.digitaloceanspaces.com',
        'region' => 'ams3',
        'bucket' => 'my-site',
        'url' => 'https://cdn.inlycore.com/my-client/my-site',
    ],
    'disks' => ['assets' => 'assets', 'files' => 'files'],
],

'media' => [
    'bucket' => [
        'endpoint' => 'https://ams3.digitaloceanspaces.com',
        'region' => 'ams3',
        'bucket' => 'site',
        'url' => 'https://cdn.example.com/site/storage',
    ],
    'disks' => ['assets' => 'web'],   // the folder the files already sit in
],

Route::middleware('throttle:120,1')->prefix('api/core/v1')->group(function () {
    Route::get('content', [ContentController::class, 'index'])->middleware('core-web.envelope:website.read');
    Route::post('drafts', [DraftsController::class, 'store'])->middleware('core-web.envelope:website.draft');
    Route::post('drafts/{id}/publish', [DraftsController::class, 'publish'])->middleware('core-web.envelope:website.publish');
});

// bootstrap/app.php
->withRouting(
    web: __DIR__.'/../routes/web.php',
    then: fn () => Route::group([], base_path('routes/core-api.php')),
)

->withMiddleware(function (Middleware $middleware) {
    $middleware->trimStrings(except: [fn (Request $request) => $request->is('api/core/v1/*')]);
    $middleware->convertEmptyStringsToNull(except: [fn (Request $request) => $request->is('api/core/v1/*')]);
})

$this->fakeCore();
$this->callSealed('GET', '/api/core/v1/content?limit=10', 'website.read')->assertOk();
$this->callSealed('POST', '/api/core/v1/drafts', 'website.draft', $body, ['environment' => 'staging'])
    ->assertForbidden()->assertJson(['error' => 'wrong_environment']);

$author = new DraftAuthor($cpUser, $name, DraftProvenance::make('content-push', ['by' => $email]), 'Pushed from local');

app(DraftWriter::class)->write($author, [
    'collection' => 'articles',
    'entry_id' => $id,            // omit for a new entry
    'fields' => ['title' => '…'],
    'base_hash' => $hash,         // the DraftBase hash read before the change
]);

$target = ProposalTargets::resolve('nav:main:default'); // tree:{collection}:{site}, global:{handle}:{site}, term:{taxonomy}:{slug}:{site}, asset:{container}::{path}

app(Proposals::class)->propose($author, $target, $newTree, Proposals::base($target));

$checks = app(ContentChecks::class);
$checks->latest('own-url-links');                 // the last run's findings
$checks->fix('own-url-links', $findingId, $author); // a draft or a proposal

return [
    'features' => ['cp_link' => true],
    'cp_link' => ['label' => 'Acme Core', 'icon' => null],
];

return [
    'features' => ['cms_sign_in' => true],
    'cms_sign_in' => [
        // Core CMS grants => Statamic role handles. Admins become super users.
        'roles' => ['cms_editor' => 'editor'],
    ],
];

return [
    'features' => ['content_sync' => true],
    'content_sync' => [
        'remote_url' => 'https://www.example.com',
    ],
];

'content_sync' => [
    'remote_url' => 'https://www.example.com',
    'tokens' => ['driver' => 'database'], // `connection` and `table` optional
],

use Inly\CoreWeb\Testing\FakesCore;

class FacilityTest extends TestCase
{
    use FakesCore;

    public function test_a_ping_refreshes_the_facility(): void
    {
        $this->fakeCore([
            'core.test/api/v1/objects/facility/*' => self::coreObjectById('facility', $resources),
            'core.test/api/v1/objects/facility*' => self::coreList($resources),
        ]);

        $this->withPingSecret()->receivePing(['type' => 'facility', 'id' => '1', 'public_id' => $uuid])->assertStatus(202);
    }
}

$whole = FacilitySnapshot::pull(CoreClient::fromConfig());
$this->answerSparseFieldsets(['manufacturer' => 'manufacturers']); // 

$this->answerRowMeta();
$this->fakeCoreCompactsMeta = false;
$full = FacilitySnapshot::pull(CoreClient::fromConfig());
$this->fakeCoreCompactsMeta = true;
$this->assertSame($full, FacilitySnapshot::pull(CoreClient::fromConfig()));
bash
  php artisan vendor:publish --tag=core-web-migrations
  php artisan migrate
  
bash
php artisan vendor:publish --tag=core-web-sync-tokens-migration
php artisan migrate
bash
php artisan core-web:deploy