@param \DateTime $date * @return string */ protected function serializeDate(DateTime $date) { return $date->format($this->getDateFormat()); } /** * Set the date format used by the model. * * @param string $format * @return $this */ public function setDateFormat($format) { $this->dateFormat = $format; return $this; } /** * Encode the given value as JSON. * * @param mixed $value * @return string */ protected function asJson($value) { return json_encode($value); } /** * Decode the given JSON back into an array or object. * * @param string $value * @param bool $asObject * @return mixed */ public function fromJson($value, $asObject = false) { return json_decode($value, ! $asObject); } /** * Clone the model into a new, non-existing instance. * * @param array|null $except * @return \FluentCrm\Framework\Database\Orm\Model */ public function replicate(array $except = null) { $defaults = [ $this->getKeyName(), $this->getCreatedAtColumn(), $this->getUpdatedAtColumn(), ]; $except = $except ? array_unique(array_merge($except, $defaults)) : $defaults; $attributes = Arr::except($this->attributes, $except); $instance = new static; $instance->setRawAttributes($attributes); return $instance->setRelations($this->relations); } /** * Get all of the current attributes on the model. * * @return array */ public function getAttributes() { return $this->attributes; } /** * Set the array of model attributes. No checking is done. * * @param array $attributes * @param bool $sync * @return $this */ public function setRawAttributes(array $attributes, $sync = false) { $this->attributes = $attributes; if ($sync) { $this->syncOriginal(); } return $this; } /** * Get the model's original attribute values. * * @param string|null $key * @param mixed $default * @return mixed|array */ public function getOriginal($key = null, $default = null) { return Arr::get($this->original, $key, $default); } /** * Sync the original attributes with the current. * * @return $this */ public function syncOriginal() { $this->original = $this->attributes; return $this; } /** * Sync a single original attribute with its current value. * * @param string $attribute * @return $this */ public function syncOriginalAttribute($attribute) { $this->original[$attribute] = $this->attributes[$attribute]; return $this; } /** * Determine if the model or given attribute(s) have been modified. * * @param array|string|null $attributes * @return bool */ public function isDirty($attributes = null) { $dirty = $this->getDirty(); if (is_null($attributes)) { return count($dirty) > 0; } if (! is_array($attributes)) { $attributes = func_get_args(); } foreach ($attributes as $attribute) { if (array_key_exists($attribute, $dirty)) { return true; } } return false; } /** * Get the attributes that have been changed since last sync. * * @return array */ public function getDirty() { $dirty = []; foreach ($this->attributes as $key => $value) { if (! array_key_exists($key, $this->original)) { $dirty[$key] = $value; } elseif ($value !== $this->original[$key] && ! $this->originalIsNumericallyEquivalent($key)) { $dirty[$key] = $value; } } return $dirty; } /** * Determine if the new and old values for a given key are numerically equivalent. * * @param string $key * @return bool */ protected function originalIsNumericallyEquivalent($key) { $current = $this->attributes[$key]; $original = $this->original[$key]; return is_numeric($current) && is_numeric($original) && strcmp((string) $current, (string) $original) === 0; } /** * Get all the loaded relations for the instance. * * @return array */ public function getRelations() { return $this->relations; } /** * Get a specified relationship. * * @param string $relation * @return mixed */ public function getRelation($relation) { return $this->relations[$relation]; } /** * Determine if the given relation is loaded. * * @param string $key * @return bool */ public function relationLoaded($key) { return array_key_exists($key, $this->relations); } /** * Set the specific relationship in the model. * * @param string $relation * @param mixed $value * @return $this */ public function setRelation($relation, $value) { $this->relations[$relation] = $value; return $this; } /** * Set the entire relations array on the model. * * @param array $relations * @return $this */ public function setRelations(array $relations) { $this->relations = $relations; return $this; } /** * Get the database connection for the model. * * @return \FluentCrm\Framework\Database\Connection */ public function getConnection() { return static::resolveConnection($this->getConnectionName()); } /** * Get the current connection name for the model. * * @return string */ public function getConnectionName() { return $this->connection; } /** * Set the connection associated with the model. * * @param string $name * @return $this */ public function setConnection($name) { $this->connection = $name; return $this; } /** * Resolve a connection instance. * * @param string|null $connection * @return \FluentCrm\Framework\Database\Connection */ public static function resolveConnection($connection = null) { return static::$resolver->connection($connection); } /** * Get the connection resolver instance. * * @return \FluentCrm\Framework\Database\ConnectionResolverInterface */ public static function getConnectionResolver() { return static::$resolver; } /** * Set the connection resolver instance. * * @param \FluentCrm\Framework\Database\ConnectionResolverInterface $resolver * @return void */ public static function setConnectionResolver(Resolver $resolver) { static::$resolver = $resolver; } /** * Unset the connection resolver for models. * * @return void */ public static function unsetConnectionResolver() { static::$resolver = null; } /** * Get the event dispatcher instance. * * @return \FluentCrm\Framework\Contracts\Events\Dispatcher */ public static function getEventDispatcher() { return static::$dispatcher; } /** * Set the event dispatcher instance. * * @param \FluentCrm\Framework\Foundation\Dispatcher $dispatcher * @return void */ public static function setEventDispatcher(Dispatcher $dispatcher) { static::$dispatcher = $dispatcher; } /** * Unset the event dispatcher for models. * * @return void */ public static function unsetEventDispatcher() { static::$dispatcher = null; } /** * Get the mutated attributes for a given instance. * * @return array */ public function getMutatedAttributes() { $class = static::class; if (! isset(static::$mutatorCache[$class])) { static::cacheMutatedAttributes($class); } return static::$mutatorCache[$class]; } /** * Extract and cache all the mutated attributes of a class. * * @param string $class * @return void */ public static function cacheMutatedAttributes($class) { $mutatedAttributes = []; // Here we will extract all of the mutated attributes so that we can quickly // spin through them after we export models to their array form, which we // need to be fast. This'll let us know the attributes that can mutate. if (preg_match_all('/(?<=^|;)get([^;]+?)Attribute(;|$)/', implode(';', get_class_methods($class)), $matches)) { foreach ($matches[1] as $match) { if (static::$snakeAttributes) { $match = Str::snake($match); } $mutatedAttributes[] = lcfirst($match); } } static::$mutatorCache[$class] = $mutatedAttributes; } /** * Dynamically retrieve attributes on the model. * * @param string $key * @return mixed */ public function __get($key) { return $this->getAttribute($key); } /** * Dynamically set attributes on the model. * * @param string $key * @param mixed $value * @return void */ public function __set($key, $value) { $this->setAttribute($key, $value); } /** * Determine if the given attribute exists. * * @param mixed $offset * @return bool */ #[\ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->$offset); } /** * Get the value for a given offset. * * @param mixed $offset * @return mixed */ #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->$offset; } /** * Set the value for a given offset. * * @param mixed $offset * @param mixed $value * @return void */ #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { $this->$offset = $value; } /** * Unset the value for a given offset. * * @param mixed $offset * @return void */ #[\ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->$offset); } /** * Determine if an attribute or relation exists on the model. * * @param string $key * @return bool */ public function __isset($key) { return ! is_null($this->getAttribute($key)); } /** * Unset an attribute on the model. * * @param string $key * @return void */ public function __unset($key) { unset($this->attributes[$key], $this->relations[$key]); } /** * Handle dynamic method calls into the model. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { if (in_array($method, ['increment', 'decrement'])) { return call_user_func_array([$this, $method], $parameters); } $query = $this->newQuery(); return call_user_func_array([$query, $method], $parameters); } /** * Handle dynamic static method calls into the method. * * @param string $method * @param array $parameters * @return mixed */ public static function __callStatic($method, $parameters) { $instance = new static; return call_user_func_array([$instance, $method], $parameters); } /** * Convert the model to its string representation. * * @return string */ public function __toString() { return $this->toJson(); } /** * When a model is being unserialized, check if it needs to be booted. * * @return void */ public function __wakeup() { $this->bootIfNotBooted(); } }