provider = $provider; $this->timestamp = current_time('mysql'); } /** * Create from array * * @param array $data * @return static */ public static function fromArray(array $data): static { $status = new static($data['provider'] ?? 'unknown'); foreach ($data as $key => $value) { if (property_exists($status, $key)) { $status->$key = $value; } } return $status; } /** * Convert to array * * @return array */ public function toArray(): array { return [ 'message_id' => $this->messageId, 'provider' => $this->provider, 'status' => $this->status, 'raw_status' => $this->rawStatus, 'to_phone' => $this->toPhone, 'from_phone' => $this->fromPhone, 'error_code' => $this->errorCode, 'error_message' => $this->errorMessage, 'timestamp' => $this->timestamp, 'account_id' => $this->accountId, 'conversation_id' => $this->conversationId, 'pricing_category' => $this->pricingCategory, 'raw_payload' => $this->rawPayload, ]; } /** * Check if this is an error status * * @return bool */ public function isError(): bool { return in_array($this->status, [ self::STATUS_FAILED, self::STATUS_UNDELIVERED, ]); } /** * Check if this is a success status * * @return bool */ public function isSuccess(): bool { return in_array($this->status, [ self::STATUS_SENT, self::STATUS_DELIVERED, self::STATUS_READ, ]); } /** * Check if message was delivered * * @return bool */ public function isDelivered(): bool { return in_array($this->status, [ self::STATUS_DELIVERED, self::STATUS_READ, ]); } /** * Check if message was read * * @return bool */ public function isRead(): bool { return $this->status === self::STATUS_READ; } /** * Map provider-specific status to normalized status * * @param string $providerStatus * @param string $provider * @return string */ public static function normalizeStatus(string $providerStatus, string $provider): string { $providerStatus = strtolower($providerStatus); // Common mappings that work across providers $commonMappings = [ 'queued' => self::STATUS_QUEUED, 'sent' => self::STATUS_SENT, 'delivered' => self::STATUS_DELIVERED, 'read' => self::STATUS_READ, 'failed' => self::STATUS_FAILED, 'undelivered' => self::STATUS_UNDELIVERED, 'deleted' => self::STATUS_DELETED, ]; if (isset($commonMappings[$providerStatus])) { return $commonMappings[$providerStatus]; } // Provider-specific mappings switch ($provider) { case 'twilio': return self::normalizeTwilioStatus($providerStatus); case '360dialog': return self::normalize360DialogStatus($providerStatus); default: return self::STATUS_UNKNOWN; } } /** * Normalize Twilio-specific status * * @param string $status * @return string */ protected static function normalizeTwilioStatus(string $status): string { $mapping = [ 'accepted' => self::STATUS_QUEUED, 'scheduled' => self::STATUS_QUEUED, 'sending' => self::STATUS_QUEUED, 'receiving' => self::STATUS_QUEUED, 'received' => self::STATUS_DELIVERED, 'canceled' => self::STATUS_FAILED, ]; return $mapping[$status] ?? self::STATUS_UNKNOWN; } /** * Normalize 360dialog-specific status * * @param string $status * @return string */ protected static function normalize360DialogStatus(string $status): string { $mapping = [ 'accepted' => self::STATUS_QUEUED, 'pending' => self::STATUS_QUEUED, 'warning' => self::STATUS_WARNING, ]; return $mapping[$status] ?? self::STATUS_UNKNOWN; } }