getItemServiceData($serviceKey, $itemID); $statusID = $opts['statusID'] ?? Service::STATUS_ACTIVE; $data = array_merge($opts['data'] ?? [], [ 'group_key' => $this->getGroupKey(), 'service_key' => $serviceKey, 'service_status' => $statusID, 'item_id' => $itemID, 'created_by' => $userID, 'settings' => $settings, 'expires' => $expires, ]); if (empty($exist['id'])) { $status = $this->getServiceStatusModel($data); if (! $status->save()) { return false; } } else { unset($data['group_key'], $data['service_key'], $data['item_id'], $data['created_by']); $exist->fill($data)->save(); } if (empty($exist['status']) || $exist['status'] != $statusID) { $this->onItemServiceStatusChange($itemID, $serviceKey, $statusID, $settings); } return true; } /** * Deactivate item service [by filter] * @param string $serviceKey * @param int|string $itemID * @param array $opts [int statusID, array filter, array update, array settings] * @return bool */ public function deactivateItemService(string $serviceKey, $itemID, array $opts = []): bool { return $this->changeItemServiceStatus($serviceKey, $itemID, Service::STATUS_EXPIRED, $opts); } /** * Deactivate service for group of items [by filter] * @param string $serviceKey * @param Closure|null $callable callback: function(ServiceStatus $status) {} * @param array $opts [int statusID, array filter, array update, array settings] * @return void */ public function deactivateItemsService(string $serviceKey, $callable = null, array $opts = []) { $opts['cursor'] = true; foreach ($this->getItemsWithActiveService($serviceKey, $opts['filter'] ?? [], $opts) as $status) { if ($callable instanceof Closure) { if ($callable($status) === false) { break; } continue; } $opts['status'] = $status; $this->changeItemServiceStatus($serviceKey, $status->item_id, Service::STATUS_EXPIRED, $opts); } } /** * Set service status * @param string $serviceKey * @param int|string $itemID * @param int $statusID * @param array $opts [int statusID, array filter, array update, array settings] * @return bool */ public function changeItemServiceStatus(string $serviceKey, $itemID, int $statusID, array $opts = []): bool { $opts = $this->defaults($opts, [ 'status' => null, 'filter' => [], 'update' => [], 'settings' => [], ]); $statusID = $opts['statusID'] ?? $statusID; $filter = array_merge($opts['filter'] ?? [], [ 'group_key' => $this->getGroupKey(), 'service_key' => $serviceKey, 'item_id' => $itemID, ]); $status = $opts['status'] ?? $this->getServiceStatusModel()->where($filter)->first(); if (! $status) { return false; } $update = array_merge($opts['update'] ?? [], ['service_status' => $statusID]); if (! empty($opts['settings'])) { $update['settings'] = array_merge($status->settings, $opts['settings']); } if (! $status->update($update)) { return false; } $this->onItemServiceStatusChange($itemID, $serviceKey, $statusID, $opts['settings']); return true; } /** * Update status in item * @param int|string $itemID * @param string $serviceKey * @param int $serviceStatus * @param array|null $serviceSettings * @return mixed|void */ public function onItemServiceStatusChange($itemID, string $serviceKey, int $serviceStatus, ?array $serviceSettings = []) { } /** * Service data for item * @param string $serviceKey * @param int|string $itemID * @param array $opts * @return \Illuminate\Support\Collection|mixed|null * @throws \bff\exception\ModelRecordNotFoundException */ public function getItemServiceData(string $serviceKey, $itemID, array $opts = []) { $opts = $this->defaults($opts, [ 'filter' => [], 'columns' => ['*'], ]); return $this->getServiceStatusModel()->one(array_merge($opts['filter'] ?? [], [ 'group_key' => $this->getGroupKey(), 'service_key' => $serviceKey, 'item_id' => $itemID, ]), $opts['columns']); } /** * Is service active for item * @param string $serviceKey * @param int|string $itemID * @param array $opts * @return bool|array */ public function isItemServiceActive(string $serviceKey, $itemID, array $opts = []) { $opts = $this->defaults($opts, [ 'extended' => false, 'filter' => [], ]); $columns = ['id']; if ($opts['extended']) { $columns[] = 'settings'; } $status = $this->getItemServiceData($serviceKey, $itemID, array_merge($opts, ['columns' => $columns])); if (empty($status)) { return false; } if ($opts['extended']) { return $status['settings']; } return true; } /** * Get item active services * @param int|string $itemID * @param array $filter * @param bool $extended * @return array */ public function getItemActiveServices($itemID, array $filter = [], bool $extended = false): array { if (empty($filter)) { $filter = ['service_status' => Service::STATUS_ACTIVE]; } return $this->getItemServices($itemID, $filter, $extended); } /** * Get item services by filter * @param int|string $itemID * @param array $filter * @param bool $extended * @return array */ public function getItemServices($itemID, array $filter, bool $extended = false): array { $filter['item_id'] = $itemID; $filter['group_key'] = $this->getGroupKey(); $query = $this->getServiceStatusModel()->where($filter); if ($extended) { return $query->get()->toArray(); } return $query->pluck('service_key')->toArray(); } /** * Get items with active service * @param string $serviceKey * @param array $filter * @param array $opts * @return array|LazyCollection items id list / cursor to iterate */ public function getItemsWithActiveService(string $serviceKey, array $filter = [], array $opts = []) { $opts = $this->defaults($opts, [ 'statusID' => Service::STATUS_ACTIVE, 'columns' => [], 'orderBy' => null, 'orderByDirection' => 'asc', 'limit' => 0, 'cursor' => false, ]); $filter['group_key'] = $this->getGroupKey(); $filter['service_key'] = $serviceKey; $filter['service_status'] = $opts['statusID']; $query = $this->getServiceStatusModel()->where($filter); if ($opts['limit'] > 0) { $query->limit($opts['limit']); } if (! empty($opts['orderBy'])) { if (mb_strtolower($opts['orderBy']) === 'rand') { $query->orderByRaw('RAND()'); } else { $query->orderBy($opts['orderBy'], $opts['orderByDirection']); } } if ($opts['cursor']) { return $query->cursor(); } if (! empty($opts['columns'])) { return $query->get($opts['columns'])->toArray(); } return $query->pluck('item_id')->toArray(); } }