<commit_before><?php namespace Illuminate\Database\Eloquent;

use DateTime;
use ArrayAccess;
use Carbon\Carbon;
use LogicException;
use JsonSerializable;
use Illuminate\Events\Dispatcher;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Support\Contracts\JsonableInterface;
use Illuminate\Support\Contracts\ArrayableInterface;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\ConnectionResolverInterface as Resolver;

abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterface, JsonSerializable {

	/**
	 * The connection name for the model.
	 *
	 * @var string
	 */
	protected $connection;

	/**
	 * The table associated with the model.
	 *
	 * @var string
	 */
	protected $table;

	/**
	 * The primary key for the model.
	 *
	 * @var string
	 */
	protected $primaryKey = 'id';

	/**
	 * The number of models to return for pagination.
	 *
	 * @var int
	 */
	protected $perPage = 15;

	/**
	 * Indicates if the IDs are auto-incrementing.
	 *
	 * @var bool
	 */
	public $incrementing = true;

	/**
	 * Indicates if the model should be timestamped.
	 *
	 * @var bool
	 */
	public $timestamps = true;

	/**
	 * The model's attributes.
	 *
	 * @var array
	 */
	protected $attributes = array();

	/**
	 * The model attribute's original state.
	 *
	 * @var array
	 */
	protected $original = array();

	/**
	 * The loaded relationships for the model.
	 *
	 * @var array
	 */
	protected $relations = array();

	/**
	 * The attributes that should be hidden for arrays.
	 *
	 * @var array
	 */
	protected $hidden = array();

	/**
	 * The attributes that should be visible in arrays.
	 *
	 * @var array
	 */
	protected $visible = array();

	/**
	 * The accessors to append to the model's array form.
	 *
	 * @var array
	 */
	protected $appends = array();

	/**
	 * The attributes that are mass assignable.
	 *
	 * @var array
	 */
	protected $fillable = array();

	/**
	 * The attributes that aren't mass assignable.
	 *
	 * @var array
	 */
	protected $guarded = array('*');

	/**
	 * The attributes that should be mutated to dates.
	 *
	 * @var array
	 */
	protected $dates = array();

	/**
	 * The relationships that should be touched on save.
	 *
	 * @var array
	 */
	protected $touches = array();

	/**
	 * User exposed observable events
	 *
	 * @var array
	 */
	protected $observables = array();

	/**
	 * The relations to eager load on every query.
	 *
	 * @var array
	 */
	protected $with = array();

	/**
	 * The class name to be used in polymorphic relations.
	 *
	 * @var string
	 */
	protected $morphClass;

	/**
	 * Indicates if the model exists.
	 *
	 * @var bool
	 */
	public $exists = false;

	/**
	 * Indicates whether attributes are snake cased on arrays.
	 *
	 * @var bool
	 */
	public static $snakeAttributes = true;

	/**
	 * The connection resolver instance.
	 *
	 * @var \Illuminate\Database\ConnectionResolverInterface
	 */
	protected static $resolver;

	/**
	 * The event dispatcher instance.
	 *
	 * @var \Illuminate\Events\Dispatcher
	 */
	protected static $dispatcher;

	/**
	 * The array of booted models.
	 *
	 * @var array
	 */
	protected static $booted = array();

	/**
	 * The array of global scopes on the model.
	 *
	 * @var array
	 */
	protected static $globalScopes = array();

	/**
	 * Indicates if all mass assignment is enabled.
	 *
	 * @var bool
	 */
	protected static $unguarded = false;

	/**
	 * The cache of the mutated attributes for each class.
	 *
	 * @var array
	 */
	protected static $mutatorCache = array();

	/**
	 * The many to many relationship methods.
	 *
	 * @var array
	 */
	public static $manyMethods = array('belongsToMany', 'morphToMany', 'morphedByMany');

	/**
	 * The name of the "created at" column.
	 *
	 * @var string
	 */
	const CREATED_AT = 'created_at';

	/**
	 * The name of the "updated at" column.
	 *
	 * @var string
	 */
	const UPDATED_AT = 'updated_at';

	/**
	 * Create a new Eloquent model instance.
	 *
	 * @param  array  $attributes
	 * @return void
	 */
	public function __construct(array $attributes = array())
	{
		$this->bootIfNotBooted();

		$this->syncOriginal();

		$this->fill($attributes);
	}

	/**
	 * Check if the model needs to be booted and if so, do it.
	 *
	 * @return void
	 */
	protected function bootIfNotBooted()
	{
		$class = get_class($this);

		if ( ! isset(static::$booted[$class]))
		{
			static::$booted[$class] = true;

			$this->fireModelEvent('booting', false);

			static::boot();

			$this->fireModelEvent('booted', false);
		}
	}

	/**
	 * The "booting" method of the model.
	 *
	 * @return void
	 */
	protected static function boot()
	{
		$class = get_called_class();

		static::$mutatorCache[$class] = array();

		// 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 will let us always know the attributes mutate.
		foreach (get_class_methods($class) as $method)
		{
			if (preg_match('/^get(.+)Attribute$/', $method, $matches))
			{
				if (static::$snakeAttributes) $matches[1] = snake_case($matches[1]);

				static::$mutatorCache[$class][] = lcfirst($matches[1]);
			}
		}

		static::bootTraits();
	}

	/**
	 * Boot all of the bootable traits on the model.
	 *
	 * @return void
	 */
	protected static function bootTraits()
	{
		foreach (class_uses_recursive(get_called_class()) as $trait)
		{
			if (method_exists(get_called_class(), $method = 'boot'.class_basename($trait)))
			{
				forward_static_call([get_called_class(), $method]);
			}
		}
	}

	/**
	 * Register a new global scope on the model.
	 *
	 * @param  \Illuminate\Database\Eloquent\ScopeInterface  $scope
	 * @return void
	 */
	public static function addGlobalScope(ScopeInterface $scope)
	{
		static::$globalScopes[get_called_class()][get_class($scope)] = $scope;
	}

	/**
	 * Determine if a model has a global scope.
	 *
	 * @param  \Illuminate\Database\Eloquent\ScopeInterface  $scope
	 * @return bool
	 */
	public static function hasGlobalScope($scope)
	{
		return ! is_null(static::getGlobalScope($scope));
	}

	/**
	 * Get a global scope registered with the modal.
	 *
	 * @param  \Illuminate\Database\Eloquent\ScopeInterface  $scope
	 * @return \Illuminate\Database\Eloquent\ScopeInterface|null
	 */
	public static function getGlobalScope($scope)
	{
		return array_first(static::$globalScopes[get_called_class()], function($key, $value) use ($scope)
		{
			return $scope instanceof $value;
		});
	}

	/**
	 * Get the global scopes for this class instance.
	 *
	 * @return \Illuminate\Database\Eloquent\ScopeInterface[]
	 */
	public function getGlobalScopes()
	{
		return array_get(static::$globalScopes, get_class($this), []);
	}

	/**
	 * Register an observer with the Model.
	 *
	 * @param  object  $class
	 * @return void
	 */
	public static function observe($class)
	{
		$instance = new static;

		$className = get_class($class);

		// When registering a model observer, we will spin through the possible events
		// and determine if this observer has that method. If it does, we will hook
		// it into the model's event system, making it convenient to watch these.
		foreach ($instance->getObservableEvents() as $event)
		{
			if (method_exists($class, $event))
			{
				static::registerModelEvent($event, $className.'@'.$event);
			}
		}
	}

	/**
	 * Fill the model with an array of attributes.
	 *
	 * @param  array  $attributes
	 * @return $this
	 *
	 * @throws MassAssignmentException
	 */
	public function fill(array $attributes)
	{
		$totallyGuarded = $this->totallyGuarded();

		foreach ($this->fillableFromArray($attributes) as $key => $value)
		{
			$key = $this->removeTableFromKey($key);

			// The developers may choose to place some attributes in the "fillable"
			// array, which means only those attributes may be set through mass
			// assignment to the model, and all others will just be ignored.
			if ($this->isFillable($key))
			{
				$this->setAttribute($key, $value);
			}
			elseif ($totallyGuarded)
			{
				throw new MassAssignmentException($key);
			}
		}

		return $this;
	}

	/**
	 * Get the fillable attributes of a given array.
	 *
	 * @param  array  $attributes
	 * @return array
	 */
	protected function fillableFromArray(array $attributes)
	{
		if (count($this->fillable) > 0 && ! static::$unguarded)
		{
			return array_intersect_key($attributes, array_flip($this->fillable));
		}

		return $attributes;
	}

	/**
	 * Create a new instance of the given model.
	 *
	 * @param  array  $attributes
	 * @param  bool   $exists
	 * @return static
	 */
	public function newInstance($attributes = array(), $exists = false)
	{
		// This method just provides a convenient way for us to generate fresh model
		// instances of this current model. It is particularly useful during the
		// hydration of new objects via the Eloquent query builder instances.
		$model = new static((array) $attributes);

		$model->exists = $exists;

		return $model;
	}

	/**
	 * Create a new model instance that is existing.
	 *
	 * @param  array  $attributes
	 * @return static
	 */
	public function newFromBuilder($attributes = array())
	{
		$instance = $this->newInstance(array(), true);

		$instance->setRawAttributes((array) $attributes, true);

		return $instance;
	}

	/**
	 * Create a collection of models from plain arrays.
	 *
	 * @param  array  $items
	 * @param  string  $connection
	 * @return \Illuminate\Database\Eloquent\Collection
	 */
	public static function hydrate(array $items, $connection = null)
	{
		$collection = with($instance = new static)->newCollection();

		foreach ($items as $item)
		{
			$model = $instance->newFromBuilder($item);

			if ( ! is_null($connection))
			{
				$model->setConnection($connection);
			}

			$collection->push($model);
		}

		return $collection;
	}

	/**
	 * Create a collection of models from a raw query.
	 *
	 * @param  string  $query
	 * @param  array  $bindings
	 * @param  string  $connection
	 * @return \Illuminate\Database\Eloquent\Collection
	 */
	public static function hydrateRaw($query, $bindings = array(), $connection = null)
	{
		$instance = new static;

		if ( ! is_null($connection))
		{
			$instance->setConnection($connection);
		}

		$items = $instance->getConnection()->select($query, $bindings);

		return static::hydrate($items, $connection);
	}

	/**
	 * Save a new model and return the instance.
	 *
	 * @param  array  $attributes
	 * @return static
	 */
	public static function create(array $attributes)
	{
		$model = new static($attributes);

		$model->save();

		return $model;
	}

	/**
	 * Get the first record matching the attributes or create it.
	 *
	 * @param  array  $attributes
	 * @return static
	 */
	public static function firstOrCreate(array $attributes)
	{
		if ( ! is_null($instance = static::where($attributes)->first()))
		{
			return $instance;
		}

		return static::create($attributes);
	}

	/**
	 * Get the first record matching the attributes or instantiate it.
	 *
	 * @param  array  $attributes
	 * @return static
	 */
	public static function firstOrNew(array $attributes)
	{
		if ( ! is_null($instance = static::where($attributes)->first()))
		{
			return $instance;
		}

		return new static($attributes);
	}

	/**
	 * Create or update a record matching the attributes, and fill it with values.
	 *
	 * @param  array  $attributes
	 * @param  array  $values
	 * @return static
	 */
	public static function updateOrCreate(array $attributes, array $values = array())
	{
		$instance = static::firstOrNew($attributes);

		$instance->fill($values)->save();

		return $instance;
	}

	/**
	 * Get the first model for the given attributes.
	 *
	 * @param  array  $attributes
	 * @return static|null
	 */
	protected static function firstByAttributes($attributes)
	{
		return static::where($attributes)->first();
	}

	/**
	 * Begin querying the model.
	 *
	 * @return \Illuminate\Database\Eloquent\Builder
	 */
	public static function query()
	{
		return (new static)->newQuery();
	}

	/**
	 * Begin querying the model on a given connection.
	 *
	 * @param  string  $connection
	 * @return \Illuminate\Database\Eloquent\Builder
	 */
	public static function on($connection = null)
	{
		// First we will just create a fresh instance of this model, and then we can
		// set the connection on the model so that it is be used for the queries
		// we execute, as well as being set on each relationship we retrieve.
		$instance = new static;

		$instance->setConnection($connection);

		return $instance->newQuery();
	}

	/**
	 * Get all of the models from the database.
	 *
	 * @param  array  $columns
	 * @return \Illuminate\Database\Eloquent\Collection|static[]
	 */
	public static function all($columns = array('*'))
	{
		$instance = new static;

		return $instance->newQuery()->get($columns);
	}

	/**
	 * Find a model by its primary key.
	 *
	 * @param  mixed  $id
	 * @param  array  $columns
	 * @return \Illuminate\Support\Collection|static
	 */
	public static function find($id, $columns = array('*'))
	{
		if (is_array($id) && empty($id)) return new Collection;

		$instance = new static;

		return $instance->newQuery()->find($id, $columns);
	}

	/**
	 * Find a model by its primary key or return new static.
	 *
	 * @param  mixed  $id
	 * @param  array  $columns
	 * @return \Illuminate\Support\Collection|static
	 */
	public static function findOrNew($id, $columns = array('*'))
	{
		if ( ! is_null($model = static::find($id, $columns))) return $model;

		return new static;
	}

	/**
	 * Find a model by its primary key or throw an exception.
	 *
	 * @param  mixed  $id
	 * @param  array  $columns
	 * @return \Illuminate\Support\Collection|static
	 *
	 * @throws ModelNotFoundException
	 */
	public static function findOrFail($id, $columns = array('*'))
	{
		if ( ! is_null($model = static::find($id, $columns))) return $model;

		throw (new ModelNotFoundException)->setModel(get_called_class());
	}

	/**
	 * Eager load relations on the model.
	 *
	 * @param  array|string  $relations
	 * @return $this
	 */
	public function load($relations)
	{
		if (is_string($relations)) $relations = func_get_args();

		$query = $this->newQuery()->with($relations);

		$query->eagerLoadRelations(array($this));

		return $this;
	}

	/**
	 * Being querying a model with eager loading.
	 *
	 * @param  array|string  $relations
	 * @return \Illuminate\Database\Eloquent\Builder|static
	 */
	public static function with($relations)
	{
		if (is_string($relations)) $relations = func_get_args();

		$instance = new static;

		return $instance->newQuery()->with($relations);
	}

	/**
	 * Define a one-to-one relationship.
	 *
	 * @param  string  $related
	 * @param  string  $foreignKey
	 * @param  string  $localKey
	 * @return \Illuminate\Database\Eloquent\Relations\HasOne
	 */
	public function hasOne($related, $foreignKey = null, $localKey = null)
	{
		$foreignKey = $foreignKey ?: $this->getForeignKey();

		$instance = new $related;

		$localKey = $localKey ?: $this->getKeyName();

		return new HasOne($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
	}

	/**
	 * Define a polymorphic one-to-one relationship.
	 *
	 * @param  string  $related
	 * @param  string  $name
	 * @param  string  $type
	 * @param  string  $id
	 * @param  string  $localKey
	 * @return \Illuminate\Database\Eloquent\Relations\MorphOne
	 */
	public function morphOne($related, $name, $type = null, $id = null, $localKey = null)
	{
		$instance = new $related;

		list($type, $id) = $this->getMorphs($name, $type, $id);

		$table = $instance->getTable();

		$localKey = $localKey ?: $this->getKeyName();

		return new MorphOne($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id, $localKey);
	}

	/**
	 * Define an inverse one-to-one or many relationship.
	 *
	 * @param  string  $related
	 * @param  string  $foreignKey
	 * @param  string  $otherKey
	 * @param  string  $relation
	 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
	 */
	public function belongsTo($related, $foreignKey = null, $otherKey = null, $relation = null)
	{
		// If no relation name was given, we will use this debug backtrace to extract
		// the calling method's name and use that as the relationship name as most
		// of the time this will be what we desire to use for the relationships.
		if (is_null($relation))
		{
			list(, $caller) = debug_backtrace(false);

			$relation = $caller['function'];
		}

		// If no foreign key was supplied, we can use a backtrace to guess the proper
		// foreign key name by using the name of the relationship function, which
		// when combined with an "_id" should conventionally match the columns.
		if (is_null($foreignKey))
		{
			$foreignKey = snake_case($relation).'_id';
		}

		$instance = new $related;

		// Once we have the foreign key names, we'll just create a new Eloquent query
		// for the related models and returns the relationship instance which will
		// actually be responsible for retrieving and hydrating every relations.
		$query = $instance->newQuery();

		$otherKey = $otherKey ?: $instance->getKeyName();

		return new BelongsTo($query, $this, $foreignKey, $otherKey, $relation);
	}

	/**
	 * Define a polymorphic, inverse one-to-one or many relationship.
	 *
	 * @param  string  $name
	 * @param  string  $type
	 * @param  string  $id
	 * @return \Illuminate\Database\Eloquent\Relations\MorphTo
	 */
	public function morphTo($name = null, $type = null, $id = null)
	{
		// If no name is provided, we will use the backtrace to get the function name
		// since that is most likely the name of the polymorphic interface. We can
		// use that to get both the class and foreign key that will be utilized.
		if (is_null($name))
		{
			list(, $caller) = debug_backtrace(false);

			$name = snake_case($caller['function']);
		}

		list($type, $id) = $this->getMorphs($name, $type, $id);

		// If the type value is null it is probably safe to assume we're eager loading
		// the relationship. When that is the case we will pass in a dummy query as
		// there are multiple types in the morph and we can't use single queries.
		if (is_null($class = $this->$type))
		{
			return new MorphTo(
				$this->newQuery(), $this, $id, null, $type, $name
			);
		}

		// If we are not eager loading the relationship we will essentially treat this
		// as a belongs-to style relationship since morph-to extends that class and
		// we will pass in the appropriate values so that it behaves as expected.
		else
		{
			$instance = new $class;

			return new MorphTo(
				$instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name
			);
		}
	}

	/**
	 * Define a one-to-many relationship.
	 *
	 * @param  string  $related
	 * @param  string  $foreignKey
	 * @param  string  $localKey
	 * @return \Illuminate\Database\Eloquent\Relations\HasMany
	 */
	public function hasMany($related, $foreignKey = null, $localKey = null)
	{
		$foreignKey = $foreignKey ?: $this->getForeignKey();

		$instance = new $related;

		$localKey = $localKey ?: $this->getKeyName();

		return new HasMany($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
	}

	/**
	 * Define a has-many-through relationship.
	 *
	 * @param  string  $related
	 * @param  string  $through
	 * @param  string|null  $firstKey
	 * @param  string|null  $secondKey
	 * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
	 */
	public function hasManyThrough($related, $through, $firstKey = null, $secondKey = null)
	{
		$through = new $through;

		$firstKey = $firstKey ?: $this->getForeignKey();

		$secondKey = $secondKey ?: $through->getForeignKey();

		return new HasManyThrough((new $related)->newQuery(), $this, $through, $firstKey, $secondKey);
	}

	/**
	 * Define a polymorphic one-to-many relationship.
	 *
	 * @param  string  $related
	 * @param  string  $name
	 * @param  string  $type
	 * @param  string  $id
	 * @param  string  $localKey
	 * @return \Illuminate\Database\Eloquent\Relations\MorphMany
	 */
	public function morphMany($related, $name, $type = null, $id = null, $localKey = null)
	{
		$instance = new $related;

		// Here we will gather up the morph type and ID for the relationship so that we
		// can properly query the intermediate table of a relation. Finally, we will
		// get the table and create the relationship instances for the developers.
		list($type, $id) = $this->getMorphs($name, $type, $id);

		$table = $instance->getTable();

		$localKey = $localKey ?: $this->getKeyName();

		return new MorphMany($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id, $localKey);
	}

	/**
	 * Define a many-to-many relationship.
	 *
	 * @param  string  $related
	 * @param  string  $table
	 * @param  string  $foreignKey
	 * @param  string  $otherKey
	 * @param  string  $relation
	 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
	 */
	public function belongsToMany($related, $table = null, $foreignKey = null, $otherKey = null, $relation = null)
	{
		// If no relationship name was passed, we will pull backtraces to get the
		// name of the calling function. We will use that function name as the
		// title of this relation since that is a great convention to apply.
		if (is_null($relation))
		{
			$relation = $this->getBelongsToManyCaller();
		}

		// First, we'll need to determine the foreign key and "other key" for the
		// relationship. Once we have determined the keys we'll make the query
		// instances as well as the relationship instances we need for this.
		$foreignKey = $foreignKey ?: $this->getForeignKey();

		$instance = new $related;

		$otherKey = $otherKey ?: $instance->getForeignKey();

		// If no table name was provided, we can guess it by concatenating the two
		// models using underscores in alphabetical order. The two model names
		// are transformed to snake case from their default CamelCase also.
		if (is_null($table))
		{
			$table = $this->joiningTable($related);
		}

		// Now we're ready to create a new query builder for the related model and
		// the relationship instances for the relation. The relations will set
		// appropriate query constraint and entirely manages the hydrations.
		$query = $instance->newQuery();

		return new BelongsToMany($query, $this, $table, $foreignKey, $otherKey, $relation);
	}

	/**
	 * Define a polymorphic many-to-many relationship.
	 *
	 * @param  string  $related
	 * @param  string  $name
	 * @param  string  $table
	 * @param  string  $foreignKey
	 * @param  string  $otherKey
	 * @param  bool    $inverse
	 * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
	 */
	public function morphToMany($related, $name, $table = null, $foreignKey = null, $otherKey = null, $inverse = false)
	{
		$caller = $this->getBelongsToManyCaller();

		// First, we will need to determine the foreign key and "other key" for the
		// relationship. Once we have determined the keys we will make the query
		// instances, as well as the relationship instances we need for these.
		$foreignKey = $foreignKey ?: $name.'_id';

		$instance = new $related;

		$otherKey = $otherKey ?: $instance->getForeignKey();

		// Now we're ready to create a new query builder for this related model and
		// the relationship instances for this relation. This relations will set
		// appropriate query constraints then entirely manages the hydrations.
		$query = $instance->newQuery();

		$table = $table ?: str_plural($name);

		return new MorphToMany(
			$query, $this, $name, $table, $foreignKey,
			$otherKey, $caller, $inverse
		);
	}

	/**
	 * Define a polymorphic, inverse many-to-many relationship.
	 *
	 * @param  string  $related
	 * @param  string  $name
	 * @param  string  $table
	 * @param  string  $foreignKey
	 * @param  string  $otherKey
	 * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
	 */
	public function morphedByMany($related, $name, $table = null, $foreignKey = null, $otherKey = null)
	{
		$foreignKey = $foreignKey ?: $this->getForeignKey();

		// For the inverse of the polymorphic many-to-many relations, we will change
		// the way we determine the foreign and other keys, as it is the opposite
		// of the morph-to-many method since we're figuring out these inverses.
		$otherKey = $otherKey ?: $name.'_id';

		return $this->morphToMany($related, $name, $table, $foreignKey, $otherKey, true);
	}

	/**
	 * Get the relationship name of the belongs to many.
	 *
	 * @return  string
	 */
	protected function getBelongsToManyCaller()
	{
		$self = __FUNCTION__;

		$caller = array_first(debug_backtrace(false), function($key, $trace) use ($self)
		{
			$caller = $trace['function'];

			return ( ! in_array($caller, Model::$manyMethods) && $caller != $self);
		});

		return ! is_null($caller) ? $caller['function'] : null;
	}

	/**
	 * Get the joining table name for a many-to-many relation.
	 *
	 * @param  string  $related
	 * @return string
	 */
	public function joiningTable($related)
	{
		// The joining table name, by convention, is simply the snake cased models
		// sorted alphabetically and concatenated with an underscore, so we can
		// just sort the models and join them together to get the table name.
		$base = snake_case(class_basename($this));

		$related = snake_case(class_basename($related));

		$models = array($related, $base);

		// Now that we have the model names in an array we can just sort them and
		// use the implode function to join them together with an underscores,
		// which is typically used by convention within the database system.
		sort($models);

		return strtolower(implode('_', $models));
	}

	/**
	 * Destroy the models for the given IDs.
	 *
	 * @param  array|int  $ids
	 * @return int
	 */
	public static function destroy($ids)
	{
		// We'll initialize a count here so we will return the total number of deletes
		// for the operation. The developers can then check this number as a boolean
		// type value or get this total count of records deleted for logging, etc.
		$count = 0;

		$ids = is_array($ids) ? $ids : func_get_args();

		$instance = new static;

		// We will actually pull the models from the database table and call delete on
		// each of them individually so that their events get fired properly with a
		// correct set of attributes in case the developers wants to check these.
		$key = $instance->getKeyName();

		foreach ($instance->whereIn($key, $ids)->get() as $model)
		{
			if ($model->delete()) $count++;
		}

		return $count;
	}

	/**
	 * Delete the model from the database.
	 *
	 * @return bool|null
	 * @throws \Exception
	 */
	public function delete()
	{
		if (is_null($this->primaryKey))
		{
			throw new \Exception("No primary key defined on model.");
		}

		if ($this->exists)
		{
			if ($this->fireModelEvent('deleting') === false) return false;

			// Here, we'll touch the owning models, verifying these timestamps get updated
			// for the models. This will allow any caching to get broken on the parents
			// by the timestamp. Then we will go ahead and delete the model instance.
			$this->touchOwners();

			$this->performDeleteOnModel();

			$this->exists = false;

			// Once the model has been deleted, we will fire off the deleted event so that
			// the developers may hook into post-delete operations. We will then return
			// a boolean true as the delete is presumably successful on the database.
			$this->fireModelEvent('deleted', false);

			return true;
		}
	}

	/**
	 * Perform the actual delete query on this model instance.
	 *
	 * @return void
	 */
	protected function performDeleteOnModel()
	{
		$this->newQuery()->where($this->getKeyName(), $this->getKey())->delete();
	}

	/**
	 * Register a saving model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function saving($callback)
	{
		static::registerModelEvent('saving', $callback);
	}

	/**
	 * Register a saved model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function saved($callback)
	{
		static::registerModelEvent('saved', $callback);
	}

	/**
	 * Register an updating model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function updating($callback)
	{
		static::registerModelEvent('updating', $callback);
	}

	/**
	 * Register an updated model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function updated($callback)
	{
		static::registerModelEvent('updated', $callback);
	}

	/**
	 * Register a creating model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function creating($callback)
	{
		static::registerModelEvent('creating', $callback);
	}

	/**
	 * Register a created model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function created($callback)
	{
		static::registerModelEvent('created', $callback);
	}

	/**
	 * Register a deleting model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function deleting($callback)
	{
		static::registerModelEvent('deleting', $callback);
	}

	/**
	 * Register a deleted model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function deleted($callback)
	{
		static::registerModelEvent('deleted', $callback);
	}

	/**
	 * Remove all of the event listeners for the model.
	 *
	 * @return void
	 */
	public static function flushEventListeners()
	{
		if ( ! isset(static::$dispatcher)) return;

		$instance = new static;

		foreach ($instance->getObservableEvents() as $event)
		{
			static::$dispatcher->forget("eloquent.{$event}: ".get_called_class());
		}
	}

	/**
	 * Register a model event with the dispatcher.
	 *
	 * @param  string  $event
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	protected static function registerModelEvent($event, $callback)
	{
		if (isset(static::$dispatcher))
		{
			$name = get_called_class();

			static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback);
		}
	}

	/**
	 * Get the observable event names.
	 *
	 * @return array
	 */
	public function getObservableEvents()
	{
		return array_merge(
			array(
				'creating', 'created', 'updating', 'updated',
				'deleting', 'deleted', 'saving', 'saved',
				'restoring', 'restored',
			),
			$this->observables
		);
	}

	/**
	 * Increment a column's value by a given amount.
	 *
	 * @param  string  $column
	 * @param  int     $amount
	 * @return int
	 */
	protected function increment($column, $amount = 1)
	{
		return $this->incrementOrDecrement($column, $amount, 'increment');
	}

	/**
	 * Decrement a column's value by a given amount.
	 *
	 * @param  string  $column
	 * @param  int     $amount
	 * @return int
	 */
	protected function decrement($column, $amount = 1)
	{
		return $this->incrementOrDecrement($column, $amount, 'decrement');
	}

	/**
	 * Run the increment or decrement method on the model.
	 *
	 * @param  string  $column
	 * @param  int     $amount
	 * @param  string  $method
	 * @return int
	 */
	protected function incrementOrDecrement($column, $amount, $method)
	{
		$query = $this->newQuery();

		if ( ! $this->exists)
		{
			return $query->{$method}($column, $amount);
		}

		$this->incrementOrDecrementAttributeValue($column, $amount, $method);

		return $query->where($this->getKeyName(), $this->getKey())->{$method}($column, $amount);
	}

	/**
	 * Increment the underlying attribute value and sync with original.
	 *
	 * @param  string  $column
	 * @param  int     $amount
	 * @param  string  $method
	 * @return void
	 */
	protected function incrementOrDecrementAttributeValue($column, $amount, $method)
	{
		$this->{$column} = $this->{$column} + ($method == 'increment' ? $amount : $amount * -1);

		$this->syncOriginalAttribute($column);
	}

	/**
	 * Update the model in the database.
	 *
	 * @param  array  $attributes
	 * @return bool|int
	 */
	public function update(array $attributes = array())
	{
		if ( ! $this->exists)
		{
			return $this->newQuery()->update($attributes);
		}

		return $this->fill($attributes)->save();
	}

	/**
	 * Save the model and all of its relationships.
	 *
	 * @return bool
	 */
	public function push()
	{
		if ( ! $this->save()) return false;

		// To sync all of the relationships to the database, we will simply spin through
		// the relationships and save each model via this "push" method, which allows
		// us to recurs into all of these nested relations for this model instance.
		foreach ($this->relations as $models)
		{
			foreach (Collection::make($models) as $model)
			{
				if ( ! $model->push()) return false;
			}
		}

		return true;
	}

	/**
	 * Save the model to the database.
	 *
	 * @param  array  $options
	 * @return bool
	 */
	public function save(array $options = array())
	{
		$query = $this->newQueryWithoutScopes();

		// If the "saving" event returns false we'll bail out of the save and return
		// false, indicating that the save failed. This gives an opportunities to
		// listeners to cancel save operations if validations fail or whatever.
		if ($this->fireModelEvent('saving') === false)
		{
			return false;
		}

		// If the model already exists in the database we can just update our record
		// that is already in this database using the current IDs in this "where"
		// clause to only update this model. Otherwise, we'll just insert them.
		if ($this->exists)
		{
			$saved = $this->performUpdate($query);
		}

		// If the model is brand new, we'll insert it into our database and set the
		// ID attribute on the model to the value of the newly inserted row's ID
		// which is typically an auto-increment value managed by the database.
		else
		{
			$saved = $this->performInsert($query);
		}

		if ($saved) $this->finishSave($options);

		return $saved;
	}

	/**
	 * Finish processing on a successful save operation.
	 *
	 * @param  array  $options
	 * @return void
	 */
	protected function finishSave(array $options)
	{
		$this->fireModelEvent('saved', false);

		$this->syncOriginal();

		if (array_get($options, 'touch', true)) $this->touchOwners();
	}

	/**
	 * Perform a model update operation.
	 *
	 * @param  \Illuminate\Database\Eloquent\Builder  $query
	 * @return bool|null
	 */
	protected function performUpdate(Builder $query)
	{
		$dirty = $this->getDirty();

		if (count($dirty) > 0)
		{
			// If the updating event returns false, we will cancel the update operation so
			// developers can hook Validation systems into their models and cancel this
			// operation if the model does not pass validation. Otherwise, we update.
			if ($this->fireModelEvent('updating') === false)
			{
				return false;
			}

			// First we need to create a fresh query instance and touch the creation and
			// update timestamp on the model which are maintained by us for developer
			// convenience. Then we will just continue saving the model instances.
			if ($this->timestamps)
			{
				$this->updateTimestamps();
			}

			// Once we have run the update operation, we will fire the "updated" event for
			// this model instance. This will allow developers to hook into these after
			// models are updated, giving them a chance to do any special processing.
			$dirty = $this->getDirty();

			if (count($dirty) > 0)
			{
				$this->setKeysForSaveQuery($query)->update($dirty);

				$this->fireModelEvent('updated', false);
			}
		}

		return true;
	}

	/**
	 * Perform a model insert operation.
	 *
	 * @param  \Illuminate\Database\Eloquent\Builder  $query
	 * @return bool
	 */
	protected function performInsert(Builder $query)
	{
		if ($this->fireModelEvent('creating') === false) return false;

		// First we'll need to create a fresh query instance and touch the creation and
		// update timestamps on this model, which are maintained by us for developer
		// convenience. After, we will just continue saving these model instances.
		if ($this->timestamps)
		{
			$this->updateTimestamps();
		}

		// If the model has an incrementing key, we can use the "insertGetId" method on
		// the query builder, which will give us back the final inserted ID for this
		// table from the database. Not all tables have to be incrementing though.
		$attributes = $this->attributes;

		if ($this->incrementing)
		{
			$this->insertAndSetId($query, $attributes);
		}

		// If the table is not incrementing we'll simply insert this attributes as they
		// are, as this attributes arrays must contain an "id" column already placed
		// there by the developer as the manually determined key for these models.
		else
		{
			$query->insert($attributes);
		}

		// We will go ahead and set the exists property to true, so that it is set when
		// the created event is fired, just in case the developer tries to update it
		// during the event. This will allow them to do so and run an update here.
		$this->exists = true;

		$this->fireModelEvent('created', false);

		return true;
	}

	/**
	 * Insert the given attributes and set the ID on the model.
	 *
	 * @param  \Illuminate\Database\Eloquent\Builder  $query
	 * @param  array  $attributes
	 * @return void
	 */
	protected function insertAndSetId(Builder $query, $attributes)
	{
		$id = $query->insertGetId($attributes, $keyName = $this->getKeyName());

		$this->setAttribute($keyName, $id);
	}

	/**
	 * Touch the owning relations of the model.
	 *
	 * @return void
	 */
	public function touchOwners()
	{
		foreach ($this->touches as $relation)
		{
			$this->$relation()->touch();
			$this->$relation->touchOwners();
		}
	}

	/**
	 * Determine if the model touches a given relation.
	 *
	 * @param  string  $relation
	 * @return bool
	 */
	public function touches($relation)
	{
		return in_array($relation, $this->touches);
	}

	/**
	 * Fire the given event for the model.
	 *<commit_msg>Spacing.<commit_after><?php namespace Illuminate\Database\Eloquent;

use DateTime;
use ArrayAccess;
use Carbon\Carbon;
use LogicException;
use JsonSerializable;
use Illuminate\Events\Dispatcher;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Support\Contracts\JsonableInterface;
use Illuminate\Support\Contracts\ArrayableInterface;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\ConnectionResolverInterface as Resolver;

abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterface, JsonSerializable {

	/**
	 * The connection name for the model.
	 *
	 * @var string
	 */
	protected $connection;

	/**
	 * The table associated with the model.
	 *
	 * @var string
	 */
	protected $table;

	/**
	 * The primary key for the model.
	 *
	 * @var string
	 */
	protected $primaryKey = 'id';

	/**
	 * The number of models to return for pagination.
	 *
	 * @var int
	 */
	protected $perPage = 15;

	/**
	 * Indicates if the IDs are auto-incrementing.
	 *
	 * @var bool
	 */
	public $incrementing = true;

	/**
	 * Indicates if the model should be timestamped.
	 *
	 * @var bool
	 */
	public $timestamps = true;

	/**
	 * The model's attributes.
	 *
	 * @var array
	 */
	protected $attributes = array();

	/**
	 * The model attribute's original state.
	 *
	 * @var array
	 */
	protected $original = array();

	/**
	 * The loaded relationships for the model.
	 *
	 * @var array
	 */
	protected $relations = array();

	/**
	 * The attributes that should be hidden for arrays.
	 *
	 * @var array
	 */
	protected $hidden = array();

	/**
	 * The attributes that should be visible in arrays.
	 *
	 * @var array
	 */
	protected $visible = array();

	/**
	 * The accessors to append to the model's array form.
	 *
	 * @var array
	 */
	protected $appends = array();

	/**
	 * The attributes that are mass assignable.
	 *
	 * @var array
	 */
	protected $fillable = array();

	/**
	 * The attributes that aren't mass assignable.
	 *
	 * @var array
	 */
	protected $guarded = array('*');

	/**
	 * The attributes that should be mutated to dates.
	 *
	 * @var array
	 */
	protected $dates = array();

	/**
	 * The relationships that should be touched on save.
	 *
	 * @var array
	 */
	protected $touches = array();

	/**
	 * User exposed observable events
	 *
	 * @var array
	 */
	protected $observables = array();

	/**
	 * The relations to eager load on every query.
	 *
	 * @var array
	 */
	protected $with = array();

	/**
	 * The class name to be used in polymorphic relations.
	 *
	 * @var string
	 */
	protected $morphClass;

	/**
	 * Indicates if the model exists.
	 *
	 * @var bool
	 */
	public $exists = false;

	/**
	 * Indicates whether attributes are snake cased on arrays.
	 *
	 * @var bool
	 */
	public static $snakeAttributes = true;

	/**
	 * The connection resolver instance.
	 *
	 * @var \Illuminate\Database\ConnectionResolverInterface
	 */
	protected static $resolver;

	/**
	 * The event dispatcher instance.
	 *
	 * @var \Illuminate\Events\Dispatcher
	 */
	protected static $dispatcher;

	/**
	 * The array of booted models.
	 *
	 * @var array
	 */
	protected static $booted = array();

	/**
	 * The array of global scopes on the model.
	 *
	 * @var array
	 */
	protected static $globalScopes = array();

	/**
	 * Indicates if all mass assignment is enabled.
	 *
	 * @var bool
	 */
	protected static $unguarded = false;

	/**
	 * The cache of the mutated attributes for each class.
	 *
	 * @var array
	 */
	protected static $mutatorCache = array();

	/**
	 * The many to many relationship methods.
	 *
	 * @var array
	 */
	public static $manyMethods = array('belongsToMany', 'morphToMany', 'morphedByMany');

	/**
	 * The name of the "created at" column.
	 *
	 * @var string
	 */
	const CREATED_AT = 'created_at';

	/**
	 * The name of the "updated at" column.
	 *
	 * @var string
	 */
	const UPDATED_AT = 'updated_at';

	/**
	 * Create a new Eloquent model instance.
	 *
	 * @param  array  $attributes
	 * @return void
	 */
	public function __construct(array $attributes = array())
	{
		$this->bootIfNotBooted();

		$this->syncOriginal();

		$this->fill($attributes);
	}

	/**
	 * Check if the model needs to be booted and if so, do it.
	 *
	 * @return void
	 */
	protected function bootIfNotBooted()
	{
		$class = get_class($this);

		if ( ! isset(static::$booted[$class]))
		{
			static::$booted[$class] = true;

			$this->fireModelEvent('booting', false);

			static::boot();

			$this->fireModelEvent('booted', false);
		}
	}

	/**
	 * The "booting" method of the model.
	 *
	 * @return void
	 */
	protected static function boot()
	{
		$class = get_called_class();

		static::$mutatorCache[$class] = array();

		// 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 will let us always know the attributes mutate.
		foreach (get_class_methods($class) as $method)
		{
			if (preg_match('/^get(.+)Attribute$/', $method, $matches))
			{
				if (static::$snakeAttributes) $matches[1] = snake_case($matches[1]);

				static::$mutatorCache[$class][] = lcfirst($matches[1]);
			}
		}

		static::bootTraits();
	}

	/**
	 * Boot all of the bootable traits on the model.
	 *
	 * @return void
	 */
	protected static function bootTraits()
	{
		foreach (class_uses_recursive(get_called_class()) as $trait)
		{
			if (method_exists(get_called_class(), $method = 'boot'.class_basename($trait)))
			{
				forward_static_call([get_called_class(), $method]);
			}
		}
	}

	/**
	 * Register a new global scope on the model.
	 *
	 * @param  \Illuminate\Database\Eloquent\ScopeInterface  $scope
	 * @return void
	 */
	public static function addGlobalScope(ScopeInterface $scope)
	{
		static::$globalScopes[get_called_class()][get_class($scope)] = $scope;
	}

	/**
	 * Determine if a model has a global scope.
	 *
	 * @param  \Illuminate\Database\Eloquent\ScopeInterface  $scope
	 * @return bool
	 */
	public static function hasGlobalScope($scope)
	{
		return ! is_null(static::getGlobalScope($scope));
	}

	/**
	 * Get a global scope registered with the modal.
	 *
	 * @param  \Illuminate\Database\Eloquent\ScopeInterface  $scope
	 * @return \Illuminate\Database\Eloquent\ScopeInterface|null
	 */
	public static function getGlobalScope($scope)
	{
		return array_first(static::$globalScopes[get_called_class()], function($key, $value) use ($scope)
		{
			return $scope instanceof $value;
		});
	}

	/**
	 * Get the global scopes for this class instance.
	 *
	 * @return \Illuminate\Database\Eloquent\ScopeInterface[]
	 */
	public function getGlobalScopes()
	{
		return array_get(static::$globalScopes, get_class($this), []);
	}

	/**
	 * Register an observer with the Model.
	 *
	 * @param  object  $class
	 * @return void
	 */
	public static function observe($class)
	{
		$instance = new static;

		$className = get_class($class);

		// When registering a model observer, we will spin through the possible events
		// and determine if this observer has that method. If it does, we will hook
		// it into the model's event system, making it convenient to watch these.
		foreach ($instance->getObservableEvents() as $event)
		{
			if (method_exists($class, $event))
			{
				static::registerModelEvent($event, $className.'@'.$event);
			}
		}
	}

	/**
	 * Fill the model with an array of attributes.
	 *
	 * @param  array  $attributes
	 * @return $this
	 *
	 * @throws MassAssignmentException
	 */
	public function fill(array $attributes)
	{
		$totallyGuarded = $this->totallyGuarded();

		foreach ($this->fillableFromArray($attributes) as $key => $value)
		{
			$key = $this->removeTableFromKey($key);

			// The developers may choose to place some attributes in the "fillable"
			// array, which means only those attributes may be set through mass
			// assignment to the model, and all others will just be ignored.
			if ($this->isFillable($key))
			{
				$this->setAttribute($key, $value);
			}
			elseif ($totallyGuarded)
			{
				throw new MassAssignmentException($key);
			}
		}

		return $this;
	}

	/**
	 * Get the fillable attributes of a given array.
	 *
	 * @param  array  $attributes
	 * @return array
	 */
	protected function fillableFromArray(array $attributes)
	{
		if (count($this->fillable) > 0 && ! static::$unguarded)
		{
			return array_intersect_key($attributes, array_flip($this->fillable));
		}

		return $attributes;
	}

	/**
	 * Create a new instance of the given model.
	 *
	 * @param  array  $attributes
	 * @param  bool   $exists
	 * @return static
	 */
	public function newInstance($attributes = array(), $exists = false)
	{
		// This method just provides a convenient way for us to generate fresh model
		// instances of this current model. It is particularly useful during the
		// hydration of new objects via the Eloquent query builder instances.
		$model = new static((array) $attributes);

		$model->exists = $exists;

		return $model;
	}

	/**
	 * Create a new model instance that is existing.
	 *
	 * @param  array  $attributes
	 * @return static
	 */
	public function newFromBuilder($attributes = array())
	{
		$instance = $this->newInstance(array(), true);

		$instance->setRawAttributes((array) $attributes, true);

		return $instance;
	}

	/**
	 * Create a collection of models from plain arrays.
	 *
	 * @param  array  $items
	 * @param  string  $connection
	 * @return \Illuminate\Database\Eloquent\Collection
	 */
	public static function hydrate(array $items, $connection = null)
	{
		$collection = with($instance = new static)->newCollection();

		foreach ($items as $item)
		{
			$model = $instance->newFromBuilder($item);

			if ( ! is_null($connection))
			{
				$model->setConnection($connection);
			}

			$collection->push($model);
		}

		return $collection;
	}

	/**
	 * Create a collection of models from a raw query.
	 *
	 * @param  string  $query
	 * @param  array  $bindings
	 * @param  string  $connection
	 * @return \Illuminate\Database\Eloquent\Collection
	 */
	public static function hydrateRaw($query, $bindings = array(), $connection = null)
	{
		$instance = new static;

		if ( ! is_null($connection))
		{
			$instance->setConnection($connection);
		}

		$items = $instance->getConnection()->select($query, $bindings);

		return static::hydrate($items, $connection);
	}

	/**
	 * Save a new model and return the instance.
	 *
	 * @param  array  $attributes
	 * @return static
	 */
	public static function create(array $attributes)
	{
		$model = new static($attributes);

		$model->save();

		return $model;
	}

	/**
	 * Get the first record matching the attributes or create it.
	 *
	 * @param  array  $attributes
	 * @return static
	 */
	public static function firstOrCreate(array $attributes)
	{
		if ( ! is_null($instance = static::where($attributes)->first()))
		{
			return $instance;
		}

		return static::create($attributes);
	}

	/**
	 * Get the first record matching the attributes or instantiate it.
	 *
	 * @param  array  $attributes
	 * @return static
	 */
	public static function firstOrNew(array $attributes)
	{
		if ( ! is_null($instance = static::where($attributes)->first()))
		{
			return $instance;
		}

		return new static($attributes);
	}

	/**
	 * Create or update a record matching the attributes, and fill it with values.
	 *
	 * @param  array  $attributes
	 * @param  array  $values
	 * @return static
	 */
	public static function updateOrCreate(array $attributes, array $values = array())
	{
		$instance = static::firstOrNew($attributes);

		$instance->fill($values)->save();

		return $instance;
	}

	/**
	 * Get the first model for the given attributes.
	 *
	 * @param  array  $attributes
	 * @return static|null
	 */
	protected static function firstByAttributes($attributes)
	{
		return static::where($attributes)->first();
	}

	/**
	 * Begin querying the model.
	 *
	 * @return \Illuminate\Database\Eloquent\Builder
	 */
	public static function query()
	{
		return (new static)->newQuery();
	}

	/**
	 * Begin querying the model on a given connection.
	 *
	 * @param  string  $connection
	 * @return \Illuminate\Database\Eloquent\Builder
	 */
	public static function on($connection = null)
	{
		// First we will just create a fresh instance of this model, and then we can
		// set the connection on the model so that it is be used for the queries
		// we execute, as well as being set on each relationship we retrieve.
		$instance = new static;

		$instance->setConnection($connection);

		return $instance->newQuery();
	}

	/**
	 * Get all of the models from the database.
	 *
	 * @param  array  $columns
	 * @return \Illuminate\Database\Eloquent\Collection|static[]
	 */
	public static function all($columns = array('*'))
	{
		$instance = new static;

		return $instance->newQuery()->get($columns);
	}

	/**
	 * Find a model by its primary key.
	 *
	 * @param  mixed  $id
	 * @param  array  $columns
	 * @return \Illuminate\Support\Collection|static
	 */
	public static function find($id, $columns = array('*'))
	{
		if (is_array($id) && empty($id)) return new Collection;

		$instance = new static;

		return $instance->newQuery()->find($id, $columns);
	}

	/**
	 * Find a model by its primary key or return new static.
	 *
	 * @param  mixed  $id
	 * @param  array  $columns
	 * @return \Illuminate\Support\Collection|static
	 */
	public static function findOrNew($id, $columns = array('*'))
	{
		if ( ! is_null($model = static::find($id, $columns))) return $model;

		return new static;
	}

	/**
	 * Find a model by its primary key or throw an exception.
	 *
	 * @param  mixed  $id
	 * @param  array  $columns
	 * @return \Illuminate\Support\Collection|static
	 *
	 * @throws ModelNotFoundException
	 */
	public static function findOrFail($id, $columns = array('*'))
	{
		if ( ! is_null($model = static::find($id, $columns))) return $model;

		throw (new ModelNotFoundException)->setModel(get_called_class());
	}

	/**
	 * Eager load relations on the model.
	 *
	 * @param  array|string  $relations
	 * @return $this
	 */
	public function load($relations)
	{
		if (is_string($relations)) $relations = func_get_args();

		$query = $this->newQuery()->with($relations);

		$query->eagerLoadRelations(array($this));

		return $this;
	}

	/**
	 * Being querying a model with eager loading.
	 *
	 * @param  array|string  $relations
	 * @return \Illuminate\Database\Eloquent\Builder|static
	 */
	public static function with($relations)
	{
		if (is_string($relations)) $relations = func_get_args();

		$instance = new static;

		return $instance->newQuery()->with($relations);
	}

	/**
	 * Define a one-to-one relationship.
	 *
	 * @param  string  $related
	 * @param  string  $foreignKey
	 * @param  string  $localKey
	 * @return \Illuminate\Database\Eloquent\Relations\HasOne
	 */
	public function hasOne($related, $foreignKey = null, $localKey = null)
	{
		$foreignKey = $foreignKey ?: $this->getForeignKey();

		$instance = new $related;

		$localKey = $localKey ?: $this->getKeyName();

		return new HasOne($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
	}

	/**
	 * Define a polymorphic one-to-one relationship.
	 *
	 * @param  string  $related
	 * @param  string  $name
	 * @param  string  $type
	 * @param  string  $id
	 * @param  string  $localKey
	 * @return \Illuminate\Database\Eloquent\Relations\MorphOne
	 */
	public function morphOne($related, $name, $type = null, $id = null, $localKey = null)
	{
		$instance = new $related;

		list($type, $id) = $this->getMorphs($name, $type, $id);

		$table = $instance->getTable();

		$localKey = $localKey ?: $this->getKeyName();

		return new MorphOne($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id, $localKey);
	}

	/**
	 * Define an inverse one-to-one or many relationship.
	 *
	 * @param  string  $related
	 * @param  string  $foreignKey
	 * @param  string  $otherKey
	 * @param  string  $relation
	 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
	 */
	public function belongsTo($related, $foreignKey = null, $otherKey = null, $relation = null)
	{
		// If no relation name was given, we will use this debug backtrace to extract
		// the calling method's name and use that as the relationship name as most
		// of the time this will be what we desire to use for the relationships.
		if (is_null($relation))
		{
			list(, $caller) = debug_backtrace(false);

			$relation = $caller['function'];
		}

		// If no foreign key was supplied, we can use a backtrace to guess the proper
		// foreign key name by using the name of the relationship function, which
		// when combined with an "_id" should conventionally match the columns.
		if (is_null($foreignKey))
		{
			$foreignKey = snake_case($relation).'_id';
		}

		$instance = new $related;

		// Once we have the foreign key names, we'll just create a new Eloquent query
		// for the related models and returns the relationship instance which will
		// actually be responsible for retrieving and hydrating every relations.
		$query = $instance->newQuery();

		$otherKey = $otherKey ?: $instance->getKeyName();

		return new BelongsTo($query, $this, $foreignKey, $otherKey, $relation);
	}

	/**
	 * Define a polymorphic, inverse one-to-one or many relationship.
	 *
	 * @param  string  $name
	 * @param  string  $type
	 * @param  string  $id
	 * @return \Illuminate\Database\Eloquent\Relations\MorphTo
	 */
	public function morphTo($name = null, $type = null, $id = null)
	{
		// If no name is provided, we will use the backtrace to get the function name
		// since that is most likely the name of the polymorphic interface. We can
		// use that to get both the class and foreign key that will be utilized.
		if (is_null($name))
		{
			list(, $caller) = debug_backtrace(false);

			$name = snake_case($caller['function']);
		}

		list($type, $id) = $this->getMorphs($name, $type, $id);

		// If the type value is null it is probably safe to assume we're eager loading
		// the relationship. When that is the case we will pass in a dummy query as
		// there are multiple types in the morph and we can't use single queries.
		if (is_null($class = $this->$type))
		{
			return new MorphTo(
				$this->newQuery(), $this, $id, null, $type, $name
			);
		}

		// If we are not eager loading the relationship we will essentially treat this
		// as a belongs-to style relationship since morph-to extends that class and
		// we will pass in the appropriate values so that it behaves as expected.
		else
		{
			$instance = new $class;

			return new MorphTo(
				$instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name
			);
		}
	}

	/**
	 * Define a one-to-many relationship.
	 *
	 * @param  string  $related
	 * @param  string  $foreignKey
	 * @param  string  $localKey
	 * @return \Illuminate\Database\Eloquent\Relations\HasMany
	 */
	public function hasMany($related, $foreignKey = null, $localKey = null)
	{
		$foreignKey = $foreignKey ?: $this->getForeignKey();

		$instance = new $related;

		$localKey = $localKey ?: $this->getKeyName();

		return new HasMany($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
	}

	/**
	 * Define a has-many-through relationship.
	 *
	 * @param  string  $related
	 * @param  string  $through
	 * @param  string|null  $firstKey
	 * @param  string|null  $secondKey
	 * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
	 */
	public function hasManyThrough($related, $through, $firstKey = null, $secondKey = null)
	{
		$through = new $through;

		$firstKey = $firstKey ?: $this->getForeignKey();

		$secondKey = $secondKey ?: $through->getForeignKey();

		return new HasManyThrough((new $related)->newQuery(), $this, $through, $firstKey, $secondKey);
	}

	/**
	 * Define a polymorphic one-to-many relationship.
	 *
	 * @param  string  $related
	 * @param  string  $name
	 * @param  string  $type
	 * @param  string  $id
	 * @param  string  $localKey
	 * @return \Illuminate\Database\Eloquent\Relations\MorphMany
	 */
	public function morphMany($related, $name, $type = null, $id = null, $localKey = null)
	{
		$instance = new $related;

		// Here we will gather up the morph type and ID for the relationship so that we
		// can properly query the intermediate table of a relation. Finally, we will
		// get the table and create the relationship instances for the developers.
		list($type, $id) = $this->getMorphs($name, $type, $id);

		$table = $instance->getTable();

		$localKey = $localKey ?: $this->getKeyName();

		return new MorphMany($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id, $localKey);
	}

	/**
	 * Define a many-to-many relationship.
	 *
	 * @param  string  $related
	 * @param  string  $table
	 * @param  string  $foreignKey
	 * @param  string  $otherKey
	 * @param  string  $relation
	 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
	 */
	public function belongsToMany($related, $table = null, $foreignKey = null, $otherKey = null, $relation = null)
	{
		// If no relationship name was passed, we will pull backtraces to get the
		// name of the calling function. We will use that function name as the
		// title of this relation since that is a great convention to apply.
		if (is_null($relation))
		{
			$relation = $this->getBelongsToManyCaller();
		}

		// First, we'll need to determine the foreign key and "other key" for the
		// relationship. Once we have determined the keys we'll make the query
		// instances as well as the relationship instances we need for this.
		$foreignKey = $foreignKey ?: $this->getForeignKey();

		$instance = new $related;

		$otherKey = $otherKey ?: $instance->getForeignKey();

		// If no table name was provided, we can guess it by concatenating the two
		// models using underscores in alphabetical order. The two model names
		// are transformed to snake case from their default CamelCase also.
		if (is_null($table))
		{
			$table = $this->joiningTable($related);
		}

		// Now we're ready to create a new query builder for the related model and
		// the relationship instances for the relation. The relations will set
		// appropriate query constraint and entirely manages the hydrations.
		$query = $instance->newQuery();

		return new BelongsToMany($query, $this, $table, $foreignKey, $otherKey, $relation);
	}

	/**
	 * Define a polymorphic many-to-many relationship.
	 *
	 * @param  string  $related
	 * @param  string  $name
	 * @param  string  $table
	 * @param  string  $foreignKey
	 * @param  string  $otherKey
	 * @param  bool    $inverse
	 * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
	 */
	public function morphToMany($related, $name, $table = null, $foreignKey = null, $otherKey = null, $inverse = false)
	{
		$caller = $this->getBelongsToManyCaller();

		// First, we will need to determine the foreign key and "other key" for the
		// relationship. Once we have determined the keys we will make the query
		// instances, as well as the relationship instances we need for these.
		$foreignKey = $foreignKey ?: $name.'_id';

		$instance = new $related;

		$otherKey = $otherKey ?: $instance->getForeignKey();

		// Now we're ready to create a new query builder for this related model and
		// the relationship instances for this relation. This relations will set
		// appropriate query constraints then entirely manages the hydrations.
		$query = $instance->newQuery();

		$table = $table ?: str_plural($name);

		return new MorphToMany(
			$query, $this, $name, $table, $foreignKey,
			$otherKey, $caller, $inverse
		);
	}

	/**
	 * Define a polymorphic, inverse many-to-many relationship.
	 *
	 * @param  string  $related
	 * @param  string  $name
	 * @param  string  $table
	 * @param  string  $foreignKey
	 * @param  string  $otherKey
	 * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
	 */
	public function morphedByMany($related, $name, $table = null, $foreignKey = null, $otherKey = null)
	{
		$foreignKey = $foreignKey ?: $this->getForeignKey();

		// For the inverse of the polymorphic many-to-many relations, we will change
		// the way we determine the foreign and other keys, as it is the opposite
		// of the morph-to-many method since we're figuring out these inverses.
		$otherKey = $otherKey ?: $name.'_id';

		return $this->morphToMany($related, $name, $table, $foreignKey, $otherKey, true);
	}

	/**
	 * Get the relationship name of the belongs to many.
	 *
	 * @return  string
	 */
	protected function getBelongsToManyCaller()
	{
		$self = __FUNCTION__;

		$caller = array_first(debug_backtrace(false), function($key, $trace) use ($self)
		{
			$caller = $trace['function'];

			return ( ! in_array($caller, Model::$manyMethods) && $caller != $self);
		});

		return ! is_null($caller) ? $caller['function'] : null;
	}

	/**
	 * Get the joining table name for a many-to-many relation.
	 *
	 * @param  string  $related
	 * @return string
	 */
	public function joiningTable($related)
	{
		// The joining table name, by convention, is simply the snake cased models
		// sorted alphabetically and concatenated with an underscore, so we can
		// just sort the models and join them together to get the table name.
		$base = snake_case(class_basename($this));

		$related = snake_case(class_basename($related));

		$models = array($related, $base);

		// Now that we have the model names in an array we can just sort them and
		// use the implode function to join them together with an underscores,
		// which is typically used by convention within the database system.
		sort($models);

		return strtolower(implode('_', $models));
	}

	/**
	 * Destroy the models for the given IDs.
	 *
	 * @param  array|int  $ids
	 * @return int
	 */
	public static function destroy($ids)
	{
		// We'll initialize a count here so we will return the total number of deletes
		// for the operation. The developers can then check this number as a boolean
		// type value or get this total count of records deleted for logging, etc.
		$count = 0;

		$ids = is_array($ids) ? $ids : func_get_args();

		$instance = new static;

		// We will actually pull the models from the database table and call delete on
		// each of them individually so that their events get fired properly with a
		// correct set of attributes in case the developers wants to check these.
		$key = $instance->getKeyName();

		foreach ($instance->whereIn($key, $ids)->get() as $model)
		{
			if ($model->delete()) $count++;
		}

		return $count;
	}

	/**
	 * Delete the model from the database.
	 *
	 * @return bool|null
	 * @throws \Exception
	 */
	public function delete()
	{
		if (is_null($this->primaryKey))
		{
			throw new \Exception("No primary key defined on model.");
		}

		if ($this->exists)
		{
			if ($this->fireModelEvent('deleting') === false) return false;

			// Here, we'll touch the owning models, verifying these timestamps get updated
			// for the models. This will allow any caching to get broken on the parents
			// by the timestamp. Then we will go ahead and delete the model instance.
			$this->touchOwners();

			$this->performDeleteOnModel();

			$this->exists = false;

			// Once the model has been deleted, we will fire off the deleted event so that
			// the developers may hook into post-delete operations. We will then return
			// a boolean true as the delete is presumably successful on the database.
			$this->fireModelEvent('deleted', false);

			return true;
		}
	}

	/**
	 * Perform the actual delete query on this model instance.
	 *
	 * @return void
	 */
	protected function performDeleteOnModel()
	{
		$this->newQuery()->where($this->getKeyName(), $this->getKey())->delete();
	}

	/**
	 * Register a saving model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function saving($callback)
	{
		static::registerModelEvent('saving', $callback);
	}

	/**
	 * Register a saved model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function saved($callback)
	{
		static::registerModelEvent('saved', $callback);
	}

	/**
	 * Register an updating model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function updating($callback)
	{
		static::registerModelEvent('updating', $callback);
	}

	/**
	 * Register an updated model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function updated($callback)
	{
		static::registerModelEvent('updated', $callback);
	}

	/**
	 * Register a creating model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function creating($callback)
	{
		static::registerModelEvent('creating', $callback);
	}

	/**
	 * Register a created model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function created($callback)
	{
		static::registerModelEvent('created', $callback);
	}

	/**
	 * Register a deleting model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function deleting($callback)
	{
		static::registerModelEvent('deleting', $callback);
	}

	/**
	 * Register a deleted model event with the dispatcher.
	 *
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	public static function deleted($callback)
	{
		static::registerModelEvent('deleted', $callback);
	}

	/**
	 * Remove all of the event listeners for the model.
	 *
	 * @return void
	 */
	public static function flushEventListeners()
	{
		if ( ! isset(static::$dispatcher)) return;

		$instance = new static;

		foreach ($instance->getObservableEvents() as $event)
		{
			static::$dispatcher->forget("eloquent.{$event}: ".get_called_class());
		}
	}

	/**
	 * Register a model event with the dispatcher.
	 *
	 * @param  string  $event
	 * @param  \Closure|string  $callback
	 * @return void
	 */
	protected static function registerModelEvent($event, $callback)
	{
		if (isset(static::$dispatcher))
		{
			$name = get_called_class();

			static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback);
		}
	}

	/**
	 * Get the observable event names.
	 *
	 * @return array
	 */
	public function getObservableEvents()
	{
		return array_merge(
			array(
				'creating', 'created', 'updating', 'updated',
				'deleting', 'deleted', 'saving', 'saved',
				'restoring', 'restored',
			),
			$this->observables
		);
	}

	/**
	 * Increment a column's value by a given amount.
	 *
	 * @param  string  $column
	 * @param  int     $amount
	 * @return int
	 */
	protected function increment($column, $amount = 1)
	{
		return $this->incrementOrDecrement($column, $amount, 'increment');
	}

	/**
	 * Decrement a column's value by a given amount.
	 *
	 * @param  string  $column
	 * @param  int     $amount
	 * @return int
	 */
	protected function decrement($column, $amount = 1)
	{
		return $this->incrementOrDecrement($column, $amount, 'decrement');
	}

	/**
	 * Run the increment or decrement method on the model.
	 *
	 * @param  string  $column
	 * @param  int     $amount
	 * @param  string  $method
	 * @return int
	 */
	protected function incrementOrDecrement($column, $amount, $method)
	{
		$query = $this->newQuery();

		if ( ! $this->exists)
		{
			return $query->{$method}($column, $amount);
		}

		$this->incrementOrDecrementAttributeValue($column, $amount, $method);

		return $query->where($this->getKeyName(), $this->getKey())->{$method}($column, $amount);
	}

	/**
	 * Increment the underlying attribute value and sync with original.
	 *
	 * @param  string  $column
	 * @param  int     $amount
	 * @param  string  $method
	 * @return void
	 */
	protected function incrementOrDecrementAttributeValue($column, $amount, $method)
	{
		$this->{$column} = $this->{$column} + ($method == 'increment' ? $amount : $amount * -1);

		$this->syncOriginalAttribute($column);
	}

	/**
	 * Update the model in the database.
	 *
	 * @param  array  $attributes
	 * @return bool|int
	 */
	public function update(array $attributes = array())
	{
		if ( ! $this->exists)
		{
			return $this->newQuery()->update($attributes);
		}

		return $this->fill($attributes)->save();
	}

	/**
	 * Save the model and all of its relationships.
	 *
	 * @return bool
	 */
	public function push()
	{
		if ( ! $this->save()) return false;

		// To sync all of the relationships to the database, we will simply spin through
		// the relationships and save each model via this "push" method, which allows
		// us to recurs into all of these nested relations for this model instance.
		foreach ($this->relations as $models)
		{
			foreach (Collection::make($models) as $model)
			{
				if ( ! $model->push()) return false;
			}
		}

		return true;
	}

	/**
	 * Save the model to the database.
	 *
	 * @param  array  $options
	 * @return bool
	 */
	public function save(array $options = array())
	{
		$query = $this->newQueryWithoutScopes();

		// If the "saving" event returns false we'll bail out of the save and return
		// false, indicating that the save failed. This gives an opportunities to
		// listeners to cancel save operations if validations fail or whatever.
		if ($this->fireModelEvent('saving') === false)
		{
			return false;
		}

		// If the model already exists in the database we can just update our record
		// that is already in this database using the current IDs in this "where"
		// clause to only update this model. Otherwise, we'll just insert them.
		if ($this->exists)
		{
			$saved = $this->performUpdate($query);
		}

		// If the model is brand new, we'll insert it into our database and set the
		// ID attribute on the model to the value of the newly inserted row's ID
		// which is typically an auto-increment value managed by the database.
		else
		{
			$saved = $this->performInsert($query);
		}

		if ($saved) $this->finishSave($options);

		return $saved;
	}

	/**
	 * Finish processing on a successful save operation.
	 *
	 * @param  array  $options
	 * @return void
	 */
	protected function finishSave(array $options)
	{
		$this->fireModelEvent('saved', false);

		$this->syncOriginal();

		if (array_get($options, 'touch', true)) $this->touchOwners();
	}

	/**
	 * Perform a model update operation.
	 *
	 * @param  \Illuminate\Database\Eloquent\Builder  $query
	 * @return bool|null
	 */
	protected function performUpdate(Builder $query)
	{
		$dirty = $this->getDirty();

		if (count($dirty) > 0)
		{
			// If the updating event returns false, we will cancel the update operation so
			// developers can hook Validation systems into their models and cancel this
			// operation if the model does not pass validation. Otherwise, we update.
			if ($this->fireModelEvent('updating') === false)
			{
				return false;
			}

			// First we need to create a fresh query instance and touch the creation and
			// update timestamp on the model which are maintained by us for developer
			// convenience. Then we will just continue saving the model instances.
			if ($this->timestamps)
			{
				$this->updateTimestamps();
			}

			// Once we have run the update operation, we will fire the "updated" event for
			// this model instance. This will allow developers to hook into these after
			// models are updated, giving them a chance to do any special processing.
			$dirty = $this->getDirty();

			if (count($dirty) > 0)
			{
				$this->setKeysForSaveQuery($query)->update($dirty);

				$this->fireModelEvent('updated', false);
			}
		}

		return true;
	}

	/**
	 * Perform a model insert operation.
	 *
	 * @param  \Illuminate\Database\Eloquent\Builder  $query
	 * @return bool
	 */
	protected function performInsert(Builder $query)
	{
		if ($this->fireModelEvent('creating') === false) return false;

		// First we'll need to create a fresh query instance and touch the creation and
		// update timestamps on this model, which are maintained by us for developer
		// convenience. After, we will just continue saving these model instances.
		if ($this->timestamps)
		{
			$this->updateTimestamps();
		}

		// If the model has an incrementing key, we can use the "insertGetId" method on
		// the query builder, which will give us back the final inserted ID for this
		// table from the database. Not all tables have to be incrementing though.
		$attributes = $this->attributes;

		if ($this->incrementing)
		{
			$this->insertAndSetId($query, $attributes);
		}

		// If the table is not incrementing we'll simply insert this attributes as they
		// are, as this attributes arrays must contain an "id" column already placed
		// there by the developer as the manually determined key for these models.
		else
		{
			$query->insert($attributes);
		}

		// We will go ahead and set the exists property to true, so that it is set when
		// the created event is fired, just in case the developer tries to update it
		// during the event. This will allow them to do so and run an update here.
		$this->exists = true;

		$this->fireModelEvent('created', false);

		return true;
	}

	/**
	 * Insert the given attributes and set the ID on the model.
	 *
	 * @param  \Illuminate\Database\Eloquent\Builder  $query
	 * @param  array  $attributes
	 * @return void
	 */
	protected function insertAndSetId(Builder $query, $attributes)
	{
		$id = $query->insertGetId($attributes, $keyName = $this->getKeyName());

		$this->setAttribute($keyName, $id);
	}

	/**
	 * Touch the owning relations of the model.
	 *
	 * @return void
	 */
	public function touchOwners()
	{
		foreach ($this->touches as $relation)
		{
			$this->$relation()->touch();

			$this->$relation->touchOwners();
		}
	}

	/**
	 * Determine if the model touches a given relation.
	 *
	 * @param  string  $relation
	 * @return bool
	 */
	public function touches($relation)
	{
		return in_array($relation, $this->touches);
	}

	/**
	 * Fire the given event for the model.
	 *
{'fraction_non_alphanumeric': 0.12805164319248827, 'fraction_numerical': 0.00031298904538341156, 'mean_word_length': 3.365059486537257, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 319, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6260123', 'n_tokens_mistral': 25679, 'n_tokens_neox': 22889, 'n_words': 7576}