postyou/dealsandprojects-bundle
A Contao bundle for managing deals and projects, giving editors structured backend modules to create, organize, and publish offers or project entries. Content is delivered through frontend modules and templates, making it straightforward to present deal listings and project showcases on a Contao sit...
This release (v0.0.15) expands a Laravel-friendly API client built around time-tracking and scheduling resources. Three things changed: TimeRecord gained new methods, a CalendarEvent endpoint was added, and getAll() now enforces a cap on fetched items.
Start by installing and publishing config:
composer require <vendor>/<package>
php artisan vendor:publish --tag=<package>-config
Look first at:
max_items/limit value tied to the getAll() cap.TimeRecord and CalendarEvent resource classes — these are your primary day-to-day surface.Your first useful call is listing records for a known timeframe:
use Vendor\Package\Facades\Client;
$records = Client::timeRecords()->getAll([
'from' => now()->subWeek()->toIso8601String(),
'to' => now()->toIso8601String(),
]);
The fastest first use case is a scheduled command that pulls the last N days of time records and writes them into a local Eloquent table for reporting — that exercises auth, the resource layer, and the new item cap all at once.
Wrap the client in a repository/service. Don't call the facade from controllers or Blade. A thin TimeRecordRepository gives you one place to handle the item cap, retries, and DTO mapping:
final class TimeRecordRepository
{
public function __construct(private Client $client) {}
public function recent(int $days = 7): Collection
{
return collect($this->client->timeRecords()->getAll([
'from' => now()->subDays($days)->startOfDay()->toIso8601String(),
'to' => now()->endOfDay()->toIso8601String(),
]))->map(fn (array $row) => TimeRecordData::fromArray($row));
}
}
Chunk around the getAll() cap. The new cap means getAll() is no longer "give me everything." Treat it as a bounded page and drive windows yourself:
$cursor = now()->subMonth();
$all = collect();
while ($cursor->lt(now())) {
$chunk = $client->timeRecords()->getAll([
'from' => $cursor->toIso8601String(),
'to' => $cursor->copy()->addWeek()->toIso8601String(),
]);
$all = $all->merge($chunk);
$cursor->addWeek();
if (count($chunk) === 0) break;
}
Use CalendarEvent for sync jobs, not request-time. Events are naturally batch-oriented. Fetch them in a queued job with ShouldBeUnique keyed on the calendar ID and sync window, then reconcile into a local calendar_events table via upsert() on the external ID.
Cast aggressively at the boundary. The new TimeRecord methods suggest richer value objects. Map API arrays into readonly DTOs or Spatie Data objects immediately, so view/consumer code is insulated from field renames in future releases.
Test against a faked HTTP layer. Use Http::fake() with fixtures captured from real responses per endpoint. Because getAll() is now capped, keep a fixture that returns exactly the cap count to assert your chunking loop terminates and advances correctly.
Schedule the sync. A php artisan schedule:run entry every 15 minutes for calendar events, hourly for time records, keeps local data fresh without hammering the API.
getAll() no longer means "all." The fetched-items cap is the single biggest behavioral change in this release. If any existing code assumed a complete dataset, it will silently under-report. Grep for getAll( before upgrading and check for loops that don't advance their window.config/<package>.php rather than relying on the default, so upgrades don't shift your data volume unexpectedly.TimeRecord new methods may be non-nullable additions. If they are declared on the class rather than a trait, mocks and test doubles implementing the old interface will break. Run your test suite immediately after the version bump.CalendarEvent is brand new — expect field churn. Pin the version range ("^0.0.15" or an exact tag) rather than using dev-main. Pre-1.0 packages rename fields freely between patches.from/to filters are inclusive.debug config flag. When a TimeRecord method returns something unexpected, the fastest path is confirming whether the API omitted the field or the package failed to hydrate it.PendingRequest, you can attach retry(), timeout(), and withToken() without forking. Look for a resolvable client in the container first — that is the cleanest hook.0.0.x is a volatile cadence; budget time for a version-bump regression run each time.How can I help you explore Laravel packages today?