v.0.1
This commit is contained in:
202
vendor/illuminate/database/Capsule/Manager.php
vendored
Executable file
202
vendor/illuminate/database/Capsule/Manager.php
vendored
Executable file
@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Capsule;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Database\Connectors\ConnectionFactory;
|
||||
use Illuminate\Database\DatabaseManager;
|
||||
use Illuminate\Database\Eloquent\Model as Eloquent;
|
||||
use Illuminate\Support\Traits\CapsuleManagerTrait;
|
||||
use PDO;
|
||||
|
||||
class Manager
|
||||
{
|
||||
use CapsuleManagerTrait;
|
||||
|
||||
/**
|
||||
* The database manager instance.
|
||||
*
|
||||
* @var \Illuminate\Database\DatabaseManager
|
||||
*/
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* Create a new database capsule manager.
|
||||
*
|
||||
* @param \Illuminate\Container\Container|null $container
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Container $container = null)
|
||||
{
|
||||
$this->setupContainer($container ?: new Container);
|
||||
|
||||
// Once we have the container setup, we will setup the default configuration
|
||||
// options in the container "config" binding. This will make the database
|
||||
// manager work correctly out of the box without extreme configuration.
|
||||
$this->setupDefaultConfiguration();
|
||||
|
||||
$this->setupManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the default database configuration options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setupDefaultConfiguration()
|
||||
{
|
||||
$this->container['config']['database.fetch'] = PDO::FETCH_OBJ;
|
||||
|
||||
$this->container['config']['database.default'] = 'default';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the database manager instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setupManager()
|
||||
{
|
||||
$factory = new ConnectionFactory($this->container);
|
||||
|
||||
$this->manager = new DatabaseManager($this->container, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a connection instance from the global manager.
|
||||
*
|
||||
* @param string|null $connection
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public static function connection($connection = null)
|
||||
{
|
||||
return static::$instance->getConnection($connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fluent query builder instance.
|
||||
*
|
||||
* @param \Closure|\Illuminate\Database\Query\Builder|string $table
|
||||
* @param string|null $as
|
||||
* @param string|null $connection
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public static function table($table, $as = null, $connection = null)
|
||||
{
|
||||
return static::$instance->connection($connection)->table($table, $as);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a schema builder instance.
|
||||
*
|
||||
* @param string|null $connection
|
||||
* @return \Illuminate\Database\Schema\Builder
|
||||
*/
|
||||
public static function schema($connection = null)
|
||||
{
|
||||
return static::$instance->connection($connection)->getSchemaBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a registered connection instance.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public function getConnection($name = null)
|
||||
{
|
||||
return $this->manager->connection($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a connection with the manager.
|
||||
*
|
||||
* @param array $config
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function addConnection(array $config, $name = 'default')
|
||||
{
|
||||
$connections = $this->container['config']['database.connections'];
|
||||
|
||||
$connections[$name] = $config;
|
||||
|
||||
$this->container['config']['database.connections'] = $connections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap Eloquent so it is ready for usage.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function bootEloquent()
|
||||
{
|
||||
Eloquent::setConnectionResolver($this->manager);
|
||||
|
||||
// If we have an event dispatcher instance, we will go ahead and register it
|
||||
// with the Eloquent ORM, allowing for model callbacks while creating and
|
||||
// updating "model" instances; however, it is not necessary to operate.
|
||||
if ($dispatcher = $this->getEventDispatcher()) {
|
||||
Eloquent::setEventDispatcher($dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fetch mode for the database connections.
|
||||
*
|
||||
* @param int $fetchMode
|
||||
* @return $this
|
||||
*/
|
||||
public function setFetchMode($fetchMode)
|
||||
{
|
||||
$this->container['config']['database.fetch'] = $fetchMode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database manager instance.
|
||||
*
|
||||
* @return \Illuminate\Database\DatabaseManager
|
||||
*/
|
||||
public function getDatabaseManager()
|
||||
{
|
||||
return $this->manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current event dispatcher instance.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Events\Dispatcher|null
|
||||
*/
|
||||
public function getEventDispatcher()
|
||||
{
|
||||
if ($this->container->bound('events')) {
|
||||
return $this->container['events'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the event dispatcher instance to be used by connections.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Events\Dispatcher $dispatcher
|
||||
* @return void
|
||||
*/
|
||||
public function setEventDispatcher(Dispatcher $dispatcher)
|
||||
{
|
||||
$this->container->instance('events', $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically pass methods to the default connection.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public static function __callStatic($method, $parameters)
|
||||
{
|
||||
return static::connection()->$method(...$parameters);
|
||||
}
|
||||
}
|
227
vendor/illuminate/database/Concerns/BuildsQueries.php
vendored
Normal file
227
vendor/illuminate/database/Concerns/BuildsQueries.php
vendored
Normal file
@ -0,0 +1,227 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Concerns;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
|
||||
trait BuildsQueries
|
||||
{
|
||||
/**
|
||||
* Chunk the results of the query.
|
||||
*
|
||||
* @param int $count
|
||||
* @param callable $callback
|
||||
* @return bool
|
||||
*/
|
||||
public function chunk($count, callable $callback)
|
||||
{
|
||||
$this->enforceOrderBy();
|
||||
|
||||
$page = 1;
|
||||
|
||||
do {
|
||||
// We'll execute the query for the given page and get the results. If there are
|
||||
// no results we can just break and return from here. When there are results
|
||||
// we will call the callback with the current chunk of these results here.
|
||||
$results = $this->forPage($page, $count)->get();
|
||||
|
||||
$countResults = $results->count();
|
||||
|
||||
if ($countResults == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// On each chunk result set, we will pass them to the callback and then let the
|
||||
// developer take care of everything within the callback, which allows us to
|
||||
// keep the memory low for spinning through large result sets for working.
|
||||
if ($callback($results, $page) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unset($results);
|
||||
|
||||
$page++;
|
||||
} while ($countResults == $count);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a callback over each item while chunking.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param int $count
|
||||
* @return bool
|
||||
*/
|
||||
public function each(callable $callback, $count = 1000)
|
||||
{
|
||||
return $this->chunk($count, function ($results) use ($callback) {
|
||||
foreach ($results as $key => $value) {
|
||||
if ($callback($value, $key) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Chunk the results of a query by comparing IDs.
|
||||
*
|
||||
* @param int $count
|
||||
* @param callable $callback
|
||||
* @param string|null $column
|
||||
* @param string|null $alias
|
||||
* @return bool
|
||||
*/
|
||||
public function chunkById($count, callable $callback, $column = null, $alias = null)
|
||||
{
|
||||
$column = $column ?? $this->defaultKeyName();
|
||||
|
||||
$alias = $alias ?? $column;
|
||||
|
||||
$lastId = null;
|
||||
|
||||
do {
|
||||
$clone = clone $this;
|
||||
|
||||
// We'll execute the query for the given page and get the results. If there are
|
||||
// no results we can just break and return from here. When there are results
|
||||
// we will call the callback with the current chunk of these results here.
|
||||
$results = $clone->forPageAfterId($count, $lastId, $column)->get();
|
||||
|
||||
$countResults = $results->count();
|
||||
|
||||
if ($countResults == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// On each chunk result set, we will pass them to the callback and then let the
|
||||
// developer take care of everything within the callback, which allows us to
|
||||
// keep the memory low for spinning through large result sets for working.
|
||||
if ($callback($results) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$lastId = $results->last()->{$alias};
|
||||
|
||||
unset($results);
|
||||
} while ($countResults == $count);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a callback over each item while chunking by ID.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param int $count
|
||||
* @param string|null $column
|
||||
* @param string|null $alias
|
||||
* @return bool
|
||||
*/
|
||||
public function eachById(callable $callback, $count = 1000, $column = null, $alias = null)
|
||||
{
|
||||
return $this->chunkById($count, function ($results) use ($callback) {
|
||||
foreach ($results as $key => $value) {
|
||||
if ($callback($value, $key) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}, $column, $alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and get the first result.
|
||||
*
|
||||
* @param array|string $columns
|
||||
* @return \Illuminate\Database\Eloquent\Model|object|static|null
|
||||
*/
|
||||
public function first($columns = ['*'])
|
||||
{
|
||||
return $this->take(1)->get($columns)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the callback's query changes if the given "value" is true.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return mixed|$this
|
||||
*/
|
||||
public function when($value, $callback, $default = null)
|
||||
{
|
||||
if ($value) {
|
||||
return $callback($this, $value) ?: $this;
|
||||
} elseif ($default) {
|
||||
return $default($this, $value) ?: $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass the query to a given callback.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function tap($callback)
|
||||
{
|
||||
return $this->when(true, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the callback's query changes if the given "value" is false.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return mixed|$this
|
||||
*/
|
||||
public function unless($value, $callback, $default = null)
|
||||
{
|
||||
if (! $value) {
|
||||
return $callback($this, $value) ?: $this;
|
||||
} elseif ($default) {
|
||||
return $default($this, $value) ?: $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new length-aware paginator instance.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $items
|
||||
* @param int $total
|
||||
* @param int $perPage
|
||||
* @param int $currentPage
|
||||
* @param array $options
|
||||
* @return \Illuminate\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
protected function paginator($items, $total, $perPage, $currentPage, $options)
|
||||
{
|
||||
return Container::getInstance()->makeWith(LengthAwarePaginator::class, compact(
|
||||
'items', 'total', 'perPage', 'currentPage', 'options'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new simple paginator instance.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $items
|
||||
* @param int $perPage
|
||||
* @param int $currentPage
|
||||
* @param array $options
|
||||
* @return \Illuminate\Pagination\Paginator
|
||||
*/
|
||||
protected function simplePaginator($items, $perPage, $currentPage, $options)
|
||||
{
|
||||
return Container::getInstance()->makeWith(Paginator::class, compact(
|
||||
'items', 'perPage', 'currentPage', 'options'
|
||||
));
|
||||
}
|
||||
}
|
292
vendor/illuminate/database/Concerns/ManagesTransactions.php
vendored
Normal file
292
vendor/illuminate/database/Concerns/ManagesTransactions.php
vendored
Normal file
@ -0,0 +1,292 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Throwable;
|
||||
|
||||
trait ManagesTransactions
|
||||
{
|
||||
/**
|
||||
* Execute a Closure within a transaction.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @param int $attempts
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function transaction(Closure $callback, $attempts = 1)
|
||||
{
|
||||
for ($currentAttempt = 1; $currentAttempt <= $attempts; $currentAttempt++) {
|
||||
$this->beginTransaction();
|
||||
|
||||
// We'll simply execute the given callback within a try / catch block and if we
|
||||
// catch any exception we can rollback this transaction so that none of this
|
||||
// gets actually persisted to a database or stored in a permanent fashion.
|
||||
try {
|
||||
$callbackResult = $callback($this);
|
||||
}
|
||||
|
||||
// If we catch an exception we'll rollback this transaction and try again if we
|
||||
// are not out of attempts. If we are out of attempts we will just throw the
|
||||
// exception back out and let the developer handle an uncaught exceptions.
|
||||
catch (Throwable $e) {
|
||||
$this->handleTransactionException(
|
||||
$e, $currentAttempt, $attempts
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
if ($this->transactions == 1) {
|
||||
$this->getPdo()->commit();
|
||||
}
|
||||
|
||||
$this->transactions = max(0, $this->transactions - 1);
|
||||
} catch (Throwable $e) {
|
||||
$this->handleCommitTransactionException(
|
||||
$e, $currentAttempt, $attempts
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->fireConnectionEvent('committed');
|
||||
|
||||
return $callbackResult;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception encountered when running a transacted statement.
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @param int $currentAttempt
|
||||
* @param int $maxAttempts
|
||||
* @return void
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
protected function handleTransactionException(Throwable $e, $currentAttempt, $maxAttempts)
|
||||
{
|
||||
// On a deadlock, MySQL rolls back the entire transaction so we can't just
|
||||
// retry the query. We have to throw this exception all the way out and
|
||||
// let the developer handle it in another way. We will decrement too.
|
||||
if ($this->causedByConcurrencyError($e) &&
|
||||
$this->transactions > 1) {
|
||||
$this->transactions--;
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
// If there was an exception we will rollback this transaction and then we
|
||||
// can check if we have exceeded the maximum attempt count for this and
|
||||
// if we haven't we will return and try this query again in our loop.
|
||||
$this->rollBack();
|
||||
|
||||
if ($this->causedByConcurrencyError($e) &&
|
||||
$currentAttempt < $maxAttempts) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new database transaction.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function beginTransaction()
|
||||
{
|
||||
$this->createTransaction();
|
||||
|
||||
$this->transactions++;
|
||||
|
||||
$this->fireConnectionEvent('beganTransaction');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a transaction within the database.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
protected function createTransaction()
|
||||
{
|
||||
if ($this->transactions == 0) {
|
||||
$this->reconnectIfMissingConnection();
|
||||
|
||||
try {
|
||||
$this->getPdo()->beginTransaction();
|
||||
} catch (Throwable $e) {
|
||||
$this->handleBeginTransactionException($e);
|
||||
}
|
||||
} elseif ($this->transactions >= 1 && $this->queryGrammar->supportsSavepoints()) {
|
||||
$this->createSavepoint();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a save point within the database.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
protected function createSavepoint()
|
||||
{
|
||||
$this->getPdo()->exec(
|
||||
$this->queryGrammar->compileSavepoint('trans'.($this->transactions + 1))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception from a transaction beginning.
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @return void
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
protected function handleBeginTransactionException(Throwable $e)
|
||||
{
|
||||
if ($this->causedByLostConnection($e)) {
|
||||
$this->reconnect();
|
||||
|
||||
$this->getPdo()->beginTransaction();
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the active database transaction.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
if ($this->transactions == 1) {
|
||||
$this->getPdo()->commit();
|
||||
}
|
||||
|
||||
$this->transactions = max(0, $this->transactions - 1);
|
||||
|
||||
$this->fireConnectionEvent('committed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception encountered when committing a transaction.
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @param int $currentAttempt
|
||||
* @param int $maxAttempts
|
||||
* @return void
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
protected function handleCommitTransactionException(Throwable $e, $currentAttempt, $maxAttempts)
|
||||
{
|
||||
$this->transactions = max(0, $this->transactions - 1);
|
||||
|
||||
if ($this->causedByConcurrencyError($e) &&
|
||||
$currentAttempt < $maxAttempts) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->causedByLostConnection($e)) {
|
||||
$this->transactions = 0;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the active database transaction.
|
||||
*
|
||||
* @param int|null $toLevel
|
||||
* @return void
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function rollBack($toLevel = null)
|
||||
{
|
||||
// We allow developers to rollback to a certain transaction level. We will verify
|
||||
// that this given transaction level is valid before attempting to rollback to
|
||||
// that level. If it's not we will just return out and not attempt anything.
|
||||
$toLevel = is_null($toLevel)
|
||||
? $this->transactions - 1
|
||||
: $toLevel;
|
||||
|
||||
if ($toLevel < 0 || $toLevel >= $this->transactions) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Next, we will actually perform this rollback within this database and fire the
|
||||
// rollback event. We will also set the current transaction level to the given
|
||||
// level that was passed into this method so it will be right from here out.
|
||||
try {
|
||||
$this->performRollBack($toLevel);
|
||||
} catch (Throwable $e) {
|
||||
$this->handleRollBackException($e);
|
||||
}
|
||||
|
||||
$this->transactions = $toLevel;
|
||||
|
||||
$this->fireConnectionEvent('rollingBack');
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a rollback within the database.
|
||||
*
|
||||
* @param int $toLevel
|
||||
* @return void
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
protected function performRollBack($toLevel)
|
||||
{
|
||||
if ($toLevel == 0) {
|
||||
$this->getPdo()->rollBack();
|
||||
} elseif ($this->queryGrammar->supportsSavepoints()) {
|
||||
$this->getPdo()->exec(
|
||||
$this->queryGrammar->compileSavepointRollBack('trans'.($toLevel + 1))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception from a rollback.
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @return void
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
protected function handleRollBackException(Throwable $e)
|
||||
{
|
||||
if ($this->causedByLostConnection($e)) {
|
||||
$this->transactions = 0;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of active transactions.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function transactionLevel()
|
||||
{
|
||||
return $this->transactions;
|
||||
}
|
||||
}
|
10
vendor/illuminate/database/ConfigurationUrlParser.php
vendored
Normal file
10
vendor/illuminate/database/ConfigurationUrlParser.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Illuminate\Support\ConfigurationUrlParser as BaseConfigurationUrlParser;
|
||||
|
||||
class ConfigurationUrlParser extends BaseConfigurationUrlParser
|
||||
{
|
||||
//
|
||||
}
|
1291
vendor/illuminate/database/Connection.php
vendored
Executable file
1291
vendor/illuminate/database/Connection.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
163
vendor/illuminate/database/ConnectionInterface.php
vendored
Executable file
163
vendor/illuminate/database/ConnectionInterface.php
vendored
Executable file
@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Closure;
|
||||
|
||||
interface ConnectionInterface
|
||||
{
|
||||
/**
|
||||
* Begin a fluent query against a database table.
|
||||
*
|
||||
* @param \Closure|\Illuminate\Database\Query\Builder|string $table
|
||||
* @param string|null $as
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function table($table, $as = null);
|
||||
|
||||
/**
|
||||
* Get a new raw query expression.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return \Illuminate\Database\Query\Expression
|
||||
*/
|
||||
public function raw($value);
|
||||
|
||||
/**
|
||||
* Run a select statement and return a single result.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @param bool $useReadPdo
|
||||
* @return mixed
|
||||
*/
|
||||
public function selectOne($query, $bindings = [], $useReadPdo = true);
|
||||
|
||||
/**
|
||||
* Run a select statement against the database.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @param bool $useReadPdo
|
||||
* @return array
|
||||
*/
|
||||
public function select($query, $bindings = [], $useReadPdo = true);
|
||||
|
||||
/**
|
||||
* Run a select statement against the database and returns a generator.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @param bool $useReadPdo
|
||||
* @return \Generator
|
||||
*/
|
||||
public function cursor($query, $bindings = [], $useReadPdo = true);
|
||||
|
||||
/**
|
||||
* Run an insert statement against the database.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @return bool
|
||||
*/
|
||||
public function insert($query, $bindings = []);
|
||||
|
||||
/**
|
||||
* Run an update statement against the database.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @return int
|
||||
*/
|
||||
public function update($query, $bindings = []);
|
||||
|
||||
/**
|
||||
* Run a delete statement against the database.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @return int
|
||||
*/
|
||||
public function delete($query, $bindings = []);
|
||||
|
||||
/**
|
||||
* Execute an SQL statement and return the boolean result.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @return bool
|
||||
*/
|
||||
public function statement($query, $bindings = []);
|
||||
|
||||
/**
|
||||
* Run an SQL statement and get the number of rows affected.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @return int
|
||||
*/
|
||||
public function affectingStatement($query, $bindings = []);
|
||||
|
||||
/**
|
||||
* Run a raw, unprepared query against the PDO connection.
|
||||
*
|
||||
* @param string $query
|
||||
* @return bool
|
||||
*/
|
||||
public function unprepared($query);
|
||||
|
||||
/**
|
||||
* Prepare the query bindings for execution.
|
||||
*
|
||||
* @param array $bindings
|
||||
* @return array
|
||||
*/
|
||||
public function prepareBindings(array $bindings);
|
||||
|
||||
/**
|
||||
* Execute a Closure within a transaction.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @param int $attempts
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function transaction(Closure $callback, $attempts = 1);
|
||||
|
||||
/**
|
||||
* Start a new database transaction.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function beginTransaction();
|
||||
|
||||
/**
|
||||
* Commit the active database transaction.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function commit();
|
||||
|
||||
/**
|
||||
* Rollback the active database transaction.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function rollBack();
|
||||
|
||||
/**
|
||||
* Get the number of active transactions.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function transactionLevel();
|
||||
|
||||
/**
|
||||
* Execute the given callback in "dry run" mode.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return array
|
||||
*/
|
||||
public function pretend(Closure $callback);
|
||||
}
|
92
vendor/illuminate/database/ConnectionResolver.php
vendored
Executable file
92
vendor/illuminate/database/ConnectionResolver.php
vendored
Executable file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
class ConnectionResolver implements ConnectionResolverInterface
|
||||
{
|
||||
/**
|
||||
* All of the registered connections.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $connections = [];
|
||||
|
||||
/**
|
||||
* The default connection name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $default;
|
||||
|
||||
/**
|
||||
* Create a new connection resolver instance.
|
||||
*
|
||||
* @param array $connections
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $connections = [])
|
||||
{
|
||||
foreach ($connections as $name => $connection) {
|
||||
$this->addConnection($name, $connection);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a database connection instance.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @return \Illuminate\Database\ConnectionInterface
|
||||
*/
|
||||
public function connection($name = null)
|
||||
{
|
||||
if (is_null($name)) {
|
||||
$name = $this->getDefaultConnection();
|
||||
}
|
||||
|
||||
return $this->connections[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a connection to the resolver.
|
||||
*
|
||||
* @param string $name
|
||||
* @param \Illuminate\Database\ConnectionInterface $connection
|
||||
* @return void
|
||||
*/
|
||||
public function addConnection($name, ConnectionInterface $connection)
|
||||
{
|
||||
$this->connections[$name] = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a connection has been registered.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasConnection($name)
|
||||
{
|
||||
return isset($this->connections[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default connection name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultConnection()
|
||||
{
|
||||
return $this->default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default connection name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaultConnection($name)
|
||||
{
|
||||
$this->default = $name;
|
||||
}
|
||||
}
|
29
vendor/illuminate/database/ConnectionResolverInterface.php
vendored
Executable file
29
vendor/illuminate/database/ConnectionResolverInterface.php
vendored
Executable file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
interface ConnectionResolverInterface
|
||||
{
|
||||
/**
|
||||
* Get a database connection instance.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @return \Illuminate\Database\ConnectionInterface
|
||||
*/
|
||||
public function connection($name = null);
|
||||
|
||||
/**
|
||||
* Get the default connection name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultConnection();
|
||||
|
||||
/**
|
||||
* Set the default connection name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaultConnection($name);
|
||||
}
|
289
vendor/illuminate/database/Connectors/ConnectionFactory.php
vendored
Executable file
289
vendor/illuminate/database/Connectors/ConnectionFactory.php
vendored
Executable file
@ -0,0 +1,289 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Database\MySqlConnection;
|
||||
use Illuminate\Database\PostgresConnection;
|
||||
use Illuminate\Database\SQLiteConnection;
|
||||
use Illuminate\Database\SqlServerConnection;
|
||||
use Illuminate\Support\Arr;
|
||||
use InvalidArgumentException;
|
||||
use PDOException;
|
||||
|
||||
class ConnectionFactory
|
||||
{
|
||||
/**
|
||||
* The IoC container instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Container\Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Create a new connection factory instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Container\Container $container
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish a PDO connection based on the configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @param string|null $name
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public function make(array $config, $name = null)
|
||||
{
|
||||
$config = $this->parseConfig($config, $name);
|
||||
|
||||
if (isset($config['read'])) {
|
||||
return $this->createReadWriteConnection($config);
|
||||
}
|
||||
|
||||
return $this->createSingleConnection($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and prepare the database configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
protected function parseConfig(array $config, $name)
|
||||
{
|
||||
return Arr::add(Arr::add($config, 'prefix', ''), 'name', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single database connection instance.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
protected function createSingleConnection(array $config)
|
||||
{
|
||||
$pdo = $this->createPdoResolver($config);
|
||||
|
||||
return $this->createConnection(
|
||||
$config['driver'], $pdo, $config['database'], $config['prefix'], $config
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a read / write database connection instance.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
protected function createReadWriteConnection(array $config)
|
||||
{
|
||||
$connection = $this->createSingleConnection($this->getWriteConfig($config));
|
||||
|
||||
return $connection->setReadPdo($this->createReadPdo($config));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PDO instance for reading.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function createReadPdo(array $config)
|
||||
{
|
||||
return $this->createPdoResolver($this->getReadConfig($config));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the read configuration for a read / write connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function getReadConfig(array $config)
|
||||
{
|
||||
return $this->mergeReadWriteConfig(
|
||||
$config, $this->getReadWriteConfig($config, 'read')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the write configuration for a read / write connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function getWriteConfig(array $config)
|
||||
{
|
||||
return $this->mergeReadWriteConfig(
|
||||
$config, $this->getReadWriteConfig($config, 'write')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a read / write level configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
protected function getReadWriteConfig(array $config, $type)
|
||||
{
|
||||
return isset($config[$type][0])
|
||||
? Arr::random($config[$type])
|
||||
: $config[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge a configuration for a read / write connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @param array $merge
|
||||
* @return array
|
||||
*/
|
||||
protected function mergeReadWriteConfig(array $config, array $merge)
|
||||
{
|
||||
return Arr::except(array_merge($config, $merge), ['read', 'write']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that resolves to a PDO instance.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function createPdoResolver(array $config)
|
||||
{
|
||||
return array_key_exists('host', $config)
|
||||
? $this->createPdoResolverWithHosts($config)
|
||||
: $this->createPdoResolverWithoutHosts($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that resolves to a PDO instance with a specific host or an array of hosts.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Closure
|
||||
*
|
||||
* @throws \PDOException
|
||||
*/
|
||||
protected function createPdoResolverWithHosts(array $config)
|
||||
{
|
||||
return function () use ($config) {
|
||||
foreach (Arr::shuffle($hosts = $this->parseHosts($config)) as $key => $host) {
|
||||
$config['host'] = $host;
|
||||
|
||||
try {
|
||||
return $this->createConnector($config)->connect($config);
|
||||
} catch (PDOException $e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
throw $e;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the hosts configuration item into an array.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function parseHosts(array $config)
|
||||
{
|
||||
$hosts = Arr::wrap($config['host']);
|
||||
|
||||
if (empty($hosts)) {
|
||||
throw new InvalidArgumentException('Database hosts array is empty.');
|
||||
}
|
||||
|
||||
return $hosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that resolves to a PDO instance where there is no configured host.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function createPdoResolverWithoutHosts(array $config)
|
||||
{
|
||||
return function () use ($config) {
|
||||
return $this->createConnector($config)->connect($config);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a connector instance based on the configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Illuminate\Database\Connectors\ConnectorInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function createConnector(array $config)
|
||||
{
|
||||
if (! isset($config['driver'])) {
|
||||
throw new InvalidArgumentException('A driver must be specified.');
|
||||
}
|
||||
|
||||
if ($this->container->bound($key = "db.connector.{$config['driver']}")) {
|
||||
return $this->container->make($key);
|
||||
}
|
||||
|
||||
switch ($config['driver']) {
|
||||
case 'mysql':
|
||||
return new MySqlConnector;
|
||||
case 'pgsql':
|
||||
return new PostgresConnector;
|
||||
case 'sqlite':
|
||||
return new SQLiteConnector;
|
||||
case 'sqlsrv':
|
||||
return new SqlServerConnector;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException("Unsupported driver [{$config['driver']}].");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new connection instance.
|
||||
*
|
||||
* @param string $driver
|
||||
* @param \PDO|\Closure $connection
|
||||
* @param string $database
|
||||
* @param string $prefix
|
||||
* @param array $config
|
||||
* @return \Illuminate\Database\Connection
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function createConnection($driver, $connection, $database, $prefix = '', array $config = [])
|
||||
{
|
||||
if ($resolver = Connection::getResolver($driver)) {
|
||||
return $resolver($connection, $database, $prefix, $config);
|
||||
}
|
||||
|
||||
switch ($driver) {
|
||||
case 'mysql':
|
||||
return new MySqlConnection($connection, $database, $prefix, $config);
|
||||
case 'pgsql':
|
||||
return new PostgresConnection($connection, $database, $prefix, $config);
|
||||
case 'sqlite':
|
||||
return new SQLiteConnection($connection, $database, $prefix, $config);
|
||||
case 'sqlsrv':
|
||||
return new SqlServerConnection($connection, $database, $prefix, $config);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException("Unsupported driver [{$driver}].");
|
||||
}
|
||||
}
|
139
vendor/illuminate/database/Connectors/Connector.php
vendored
Executable file
139
vendor/illuminate/database/Connectors/Connector.php
vendored
Executable file
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
use Doctrine\DBAL\Driver\PDOConnection;
|
||||
use Exception;
|
||||
use Illuminate\Database\DetectsLostConnections;
|
||||
use PDO;
|
||||
use Throwable;
|
||||
|
||||
class Connector
|
||||
{
|
||||
use DetectsLostConnections;
|
||||
|
||||
/**
|
||||
* The default PDO connection options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [
|
||||
PDO::ATTR_CASE => PDO::CASE_NATURAL,
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
|
||||
PDO::ATTR_STRINGIFY_FETCHES => false,
|
||||
PDO::ATTR_EMULATE_PREPARES => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a new PDO connection.
|
||||
*
|
||||
* @param string $dsn
|
||||
* @param array $config
|
||||
* @param array $options
|
||||
* @return \PDO
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function createConnection($dsn, array $config, array $options)
|
||||
{
|
||||
[$username, $password] = [
|
||||
$config['username'] ?? null, $config['password'] ?? null,
|
||||
];
|
||||
|
||||
try {
|
||||
return $this->createPdoConnection(
|
||||
$dsn, $username, $password, $options
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
return $this->tryAgainIfCausedByLostConnection(
|
||||
$e, $dsn, $username, $password, $options
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PDO connection instance.
|
||||
*
|
||||
* @param string $dsn
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param array $options
|
||||
* @return \PDO
|
||||
*/
|
||||
protected function createPdoConnection($dsn, $username, $password, $options)
|
||||
{
|
||||
if (class_exists(PDOConnection::class) && ! $this->isPersistentConnection($options)) {
|
||||
return new PDOConnection($dsn, $username, $password, $options);
|
||||
}
|
||||
|
||||
return new PDO($dsn, $username, $password, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the connection is persistent.
|
||||
*
|
||||
* @param array $options
|
||||
* @return bool
|
||||
*/
|
||||
protected function isPersistentConnection($options)
|
||||
{
|
||||
return isset($options[PDO::ATTR_PERSISTENT]) &&
|
||||
$options[PDO::ATTR_PERSISTENT];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception that occurred during connect execution.
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @param string $dsn
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param array $options
|
||||
* @return \PDO
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function tryAgainIfCausedByLostConnection(Throwable $e, $dsn, $username, $password, $options)
|
||||
{
|
||||
if ($this->causedByLostConnection($e)) {
|
||||
return $this->createPdoConnection($dsn, $username, $password, $options);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PDO options based on the configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
public function getOptions(array $config)
|
||||
{
|
||||
$options = $config['options'] ?? [];
|
||||
|
||||
return array_diff_key($this->options, $options) + $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default PDO connection options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDefaultOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default PDO connection options.
|
||||
*
|
||||
* @param array $options
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaultOptions(array $options)
|
||||
{
|
||||
$this->options = $options;
|
||||
}
|
||||
}
|
14
vendor/illuminate/database/Connectors/ConnectorInterface.php
vendored
Executable file
14
vendor/illuminate/database/Connectors/ConnectorInterface.php
vendored
Executable file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
interface ConnectorInterface
|
||||
{
|
||||
/**
|
||||
* Establish a database connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \PDO
|
||||
*/
|
||||
public function connect(array $config);
|
||||
}
|
208
vendor/illuminate/database/Connectors/MySqlConnector.php
vendored
Executable file
208
vendor/illuminate/database/Connectors/MySqlConnector.php
vendored
Executable file
@ -0,0 +1,208 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
use PDO;
|
||||
|
||||
class MySqlConnector extends Connector implements ConnectorInterface
|
||||
{
|
||||
/**
|
||||
* Establish a database connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \PDO
|
||||
*/
|
||||
public function connect(array $config)
|
||||
{
|
||||
$dsn = $this->getDsn($config);
|
||||
|
||||
$options = $this->getOptions($config);
|
||||
|
||||
// We need to grab the PDO options that should be used while making the brand
|
||||
// new connection instance. The PDO options control various aspects of the
|
||||
// connection's behavior, and some might be specified by the developers.
|
||||
$connection = $this->createConnection($dsn, $config, $options);
|
||||
|
||||
if (! empty($config['database'])) {
|
||||
$connection->exec("use `{$config['database']}`;");
|
||||
}
|
||||
|
||||
$this->configureIsolationLevel($connection, $config);
|
||||
|
||||
$this->configureEncoding($connection, $config);
|
||||
|
||||
// Next, we will check to see if a timezone has been specified in this config
|
||||
// and if it has we will issue a statement to modify the timezone with the
|
||||
// database. Setting this DB timezone is an optional configuration item.
|
||||
$this->configureTimezone($connection, $config);
|
||||
|
||||
$this->setModes($connection, $config);
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection transaction isolation level.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureIsolationLevel($connection, array $config)
|
||||
{
|
||||
if (! isset($config['isolation_level'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$connection->prepare(
|
||||
"SET SESSION TRANSACTION ISOLATION LEVEL {$config['isolation_level']}"
|
||||
)->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection character set and collation.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void|\PDO
|
||||
*/
|
||||
protected function configureEncoding($connection, array $config)
|
||||
{
|
||||
if (! isset($config['charset'])) {
|
||||
return $connection;
|
||||
}
|
||||
|
||||
$connection->prepare(
|
||||
"set names '{$config['charset']}'".$this->getCollation($config)
|
||||
)->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the collation for the configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getCollation(array $config)
|
||||
{
|
||||
return isset($config['collation']) ? " collate '{$config['collation']}'" : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timezone on the connection.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureTimezone($connection, array $config)
|
||||
{
|
||||
if (isset($config['timezone'])) {
|
||||
$connection->prepare('set time_zone="'.$config['timezone'].'"')->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a DSN string from a configuration.
|
||||
*
|
||||
* Chooses socket or host/port based on the 'unix_socket' config value.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getDsn(array $config)
|
||||
{
|
||||
return $this->hasSocket($config)
|
||||
? $this->getSocketDsn($config)
|
||||
: $this->getHostDsn($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given configuration array has a UNIX socket value.
|
||||
*
|
||||
* @param array $config
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasSocket(array $config)
|
||||
{
|
||||
return isset($config['unix_socket']) && ! empty($config['unix_socket']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DSN string for a socket configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getSocketDsn(array $config)
|
||||
{
|
||||
return "mysql:unix_socket={$config['unix_socket']};dbname={$config['database']}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DSN string for a host / port configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getHostDsn(array $config)
|
||||
{
|
||||
extract($config, EXTR_SKIP);
|
||||
|
||||
return isset($port)
|
||||
? "mysql:host={$host};port={$port};dbname={$database}"
|
||||
: "mysql:host={$host};dbname={$database}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the modes for the connection.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function setModes(PDO $connection, array $config)
|
||||
{
|
||||
if (isset($config['modes'])) {
|
||||
$this->setCustomModes($connection, $config);
|
||||
} elseif (isset($config['strict'])) {
|
||||
if ($config['strict']) {
|
||||
$connection->prepare($this->strictMode($connection, $config))->execute();
|
||||
} else {
|
||||
$connection->prepare("set session sql_mode='NO_ENGINE_SUBSTITUTION'")->execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom modes on the connection.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function setCustomModes(PDO $connection, array $config)
|
||||
{
|
||||
$modes = implode(',', $config['modes']);
|
||||
|
||||
$connection->prepare("set session sql_mode='{$modes}'")->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query to enable strict mode.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function strictMode(PDO $connection, $config)
|
||||
{
|
||||
$version = $config['version'] ?? $connection->getAttribute(PDO::ATTR_SERVER_VERSION);
|
||||
|
||||
if (version_compare($version, '8.0.11') >= 0) {
|
||||
return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'";
|
||||
}
|
||||
|
||||
return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'";
|
||||
}
|
||||
}
|
194
vendor/illuminate/database/Connectors/PostgresConnector.php
vendored
Executable file
194
vendor/illuminate/database/Connectors/PostgresConnector.php
vendored
Executable file
@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
use PDO;
|
||||
|
||||
class PostgresConnector extends Connector implements ConnectorInterface
|
||||
{
|
||||
/**
|
||||
* The default PDO connection options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [
|
||||
PDO::ATTR_CASE => PDO::CASE_NATURAL,
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
|
||||
PDO::ATTR_STRINGIFY_FETCHES => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* Establish a database connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \PDO
|
||||
*/
|
||||
public function connect(array $config)
|
||||
{
|
||||
// First we'll create the basic DSN and connection instance connecting to the
|
||||
// using the configuration option specified by the developer. We will also
|
||||
// set the default character set on the connections to UTF-8 by default.
|
||||
$connection = $this->createConnection(
|
||||
$this->getDsn($config), $config, $this->getOptions($config)
|
||||
);
|
||||
|
||||
$this->configureEncoding($connection, $config);
|
||||
|
||||
// Next, we will check to see if a timezone has been specified in this config
|
||||
// and if it has we will issue a statement to modify the timezone with the
|
||||
// database. Setting this DB timezone is an optional configuration item.
|
||||
$this->configureTimezone($connection, $config);
|
||||
|
||||
$this->configureSchema($connection, $config);
|
||||
|
||||
// Postgres allows an application_name to be set by the user and this name is
|
||||
// used to when monitoring the application with pg_stat_activity. So we'll
|
||||
// determine if the option has been specified and run a statement if so.
|
||||
$this->configureApplicationName($connection, $config);
|
||||
|
||||
$this->configureSynchronousCommit($connection, $config);
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection character set and collation.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureEncoding($connection, $config)
|
||||
{
|
||||
if (! isset($config['charset'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$connection->prepare("set names '{$config['charset']}'")->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timezone on the connection.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureTimezone($connection, array $config)
|
||||
{
|
||||
if (isset($config['timezone'])) {
|
||||
$timezone = $config['timezone'];
|
||||
|
||||
$connection->prepare("set time zone '{$timezone}'")->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the schema on the connection.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureSchema($connection, $config)
|
||||
{
|
||||
if (isset($config['schema'])) {
|
||||
$schema = $this->formatSchema($config['schema']);
|
||||
|
||||
$connection->prepare("set search_path to {$schema}")->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the schema for the DSN.
|
||||
*
|
||||
* @param array|string $schema
|
||||
* @return string
|
||||
*/
|
||||
protected function formatSchema($schema)
|
||||
{
|
||||
if (is_array($schema)) {
|
||||
return '"'.implode('", "', $schema).'"';
|
||||
}
|
||||
|
||||
return '"'.$schema.'"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the schema on the connection.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureApplicationName($connection, $config)
|
||||
{
|
||||
if (isset($config['application_name'])) {
|
||||
$applicationName = $config['application_name'];
|
||||
|
||||
$connection->prepare("set application_name to '$applicationName'")->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a DSN string from a configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getDsn(array $config)
|
||||
{
|
||||
// First we will create the basic DSN setup as well as the port if it is in
|
||||
// in the configuration options. This will give us the basic DSN we will
|
||||
// need to establish the PDO connections and return them back for use.
|
||||
extract($config, EXTR_SKIP);
|
||||
|
||||
$host = isset($host) ? "host={$host};" : '';
|
||||
|
||||
$dsn = "pgsql:{$host}dbname={$database}";
|
||||
|
||||
// If a port was specified, we will add it to this Postgres DSN connections
|
||||
// format. Once we have done that we are ready to return this connection
|
||||
// string back out for usage, as this has been fully constructed here.
|
||||
if (isset($config['port'])) {
|
||||
$dsn .= ";port={$port}";
|
||||
}
|
||||
|
||||
return $this->addSslOptions($dsn, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the SSL options to the DSN.
|
||||
*
|
||||
* @param string $dsn
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function addSslOptions($dsn, array $config)
|
||||
{
|
||||
foreach (['sslmode', 'sslcert', 'sslkey', 'sslrootcert'] as $option) {
|
||||
if (isset($config[$option])) {
|
||||
$dsn .= ";{$option}={$config[$option]}";
|
||||
}
|
||||
}
|
||||
|
||||
return $dsn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the synchronous_commit setting.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureSynchronousCommit($connection, array $config)
|
||||
{
|
||||
if (! isset($config['synchronous_commit'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$connection->prepare("set synchronous_commit to '{$config['synchronous_commit']}'")->execute();
|
||||
}
|
||||
}
|
39
vendor/illuminate/database/Connectors/SQLiteConnector.php
vendored
Executable file
39
vendor/illuminate/database/Connectors/SQLiteConnector.php
vendored
Executable file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class SQLiteConnector extends Connector implements ConnectorInterface
|
||||
{
|
||||
/**
|
||||
* Establish a database connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \PDO
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function connect(array $config)
|
||||
{
|
||||
$options = $this->getOptions($config);
|
||||
|
||||
// SQLite supports "in-memory" databases that only last as long as the owning
|
||||
// connection does. These are useful for tests or for short lifetime store
|
||||
// querying. In-memory databases may only have a single open connection.
|
||||
if ($config['database'] === ':memory:') {
|
||||
return $this->createConnection('sqlite::memory:', $config, $options);
|
||||
}
|
||||
|
||||
$path = realpath($config['database']);
|
||||
|
||||
// Here we'll verify that the SQLite database exists before going any further
|
||||
// as the developer probably wants to know if the database exists and this
|
||||
// SQLite driver will not throw any exception if it does not by default.
|
||||
if ($path === false) {
|
||||
throw new InvalidArgumentException("Database ({$config['database']}) does not exist.");
|
||||
}
|
||||
|
||||
return $this->createConnection("sqlite:{$path}", $config, $options);
|
||||
}
|
||||
}
|
205
vendor/illuminate/database/Connectors/SqlServerConnector.php
vendored
Executable file
205
vendor/illuminate/database/Connectors/SqlServerConnector.php
vendored
Executable file
@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use PDO;
|
||||
|
||||
class SqlServerConnector extends Connector implements ConnectorInterface
|
||||
{
|
||||
/**
|
||||
* The PDO connection options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [
|
||||
PDO::ATTR_CASE => PDO::CASE_NATURAL,
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
|
||||
PDO::ATTR_STRINGIFY_FETCHES => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* Establish a database connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \PDO
|
||||
*/
|
||||
public function connect(array $config)
|
||||
{
|
||||
$options = $this->getOptions($config);
|
||||
|
||||
return $this->createConnection($this->getDsn($config), $config, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a DSN string from a configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getDsn(array $config)
|
||||
{
|
||||
// First we will create the basic DSN setup as well as the port if it is in
|
||||
// in the configuration options. This will give us the basic DSN we will
|
||||
// need to establish the PDO connections and return them back for use.
|
||||
if ($this->prefersOdbc($config)) {
|
||||
return $this->getOdbcDsn($config);
|
||||
}
|
||||
|
||||
if (in_array('sqlsrv', $this->getAvailableDrivers())) {
|
||||
return $this->getSqlSrvDsn($config);
|
||||
} else {
|
||||
return $this->getDblibDsn($config);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the database configuration prefers ODBC.
|
||||
*
|
||||
* @param array $config
|
||||
* @return bool
|
||||
*/
|
||||
protected function prefersOdbc(array $config)
|
||||
{
|
||||
return in_array('odbc', $this->getAvailableDrivers()) &&
|
||||
($config['odbc'] ?? null) === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DSN string for a DbLib connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getDblibDsn(array $config)
|
||||
{
|
||||
return $this->buildConnectString('dblib', array_merge([
|
||||
'host' => $this->buildHostString($config, ':'),
|
||||
'dbname' => $config['database'],
|
||||
], Arr::only($config, ['appname', 'charset', 'version'])));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DSN string for an ODBC connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getOdbcDsn(array $config)
|
||||
{
|
||||
return isset($config['odbc_datasource_name'])
|
||||
? 'odbc:'.$config['odbc_datasource_name'] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DSN string for a SqlSrv connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getSqlSrvDsn(array $config)
|
||||
{
|
||||
$arguments = [
|
||||
'Server' => $this->buildHostString($config, ','),
|
||||
];
|
||||
|
||||
if (isset($config['database'])) {
|
||||
$arguments['Database'] = $config['database'];
|
||||
}
|
||||
|
||||
if (isset($config['readonly'])) {
|
||||
$arguments['ApplicationIntent'] = 'ReadOnly';
|
||||
}
|
||||
|
||||
if (isset($config['pooling']) && $config['pooling'] === false) {
|
||||
$arguments['ConnectionPooling'] = '0';
|
||||
}
|
||||
|
||||
if (isset($config['appname'])) {
|
||||
$arguments['APP'] = $config['appname'];
|
||||
}
|
||||
|
||||
if (isset($config['encrypt'])) {
|
||||
$arguments['Encrypt'] = $config['encrypt'];
|
||||
}
|
||||
|
||||
if (isset($config['trust_server_certificate'])) {
|
||||
$arguments['TrustServerCertificate'] = $config['trust_server_certificate'];
|
||||
}
|
||||
|
||||
if (isset($config['multiple_active_result_sets']) && $config['multiple_active_result_sets'] === false) {
|
||||
$arguments['MultipleActiveResultSets'] = 'false';
|
||||
}
|
||||
|
||||
if (isset($config['transaction_isolation'])) {
|
||||
$arguments['TransactionIsolation'] = $config['transaction_isolation'];
|
||||
}
|
||||
|
||||
if (isset($config['multi_subnet_failover'])) {
|
||||
$arguments['MultiSubnetFailover'] = $config['multi_subnet_failover'];
|
||||
}
|
||||
|
||||
if (isset($config['column_encryption'])) {
|
||||
$arguments['ColumnEncryption'] = $config['column_encryption'];
|
||||
}
|
||||
|
||||
if (isset($config['key_store_authentication'])) {
|
||||
$arguments['KeyStoreAuthentication'] = $config['key_store_authentication'];
|
||||
}
|
||||
|
||||
if (isset($config['key_store_principal_id'])) {
|
||||
$arguments['KeyStorePrincipalId'] = $config['key_store_principal_id'];
|
||||
}
|
||||
|
||||
if (isset($config['key_store_secret'])) {
|
||||
$arguments['KeyStoreSecret'] = $config['key_store_secret'];
|
||||
}
|
||||
|
||||
if (isset($config['login_timeout'])) {
|
||||
$arguments['LoginTimeout'] = $config['login_timeout'];
|
||||
}
|
||||
|
||||
return $this->buildConnectString('sqlsrv', $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a connection string from the given arguments.
|
||||
*
|
||||
* @param string $driver
|
||||
* @param array $arguments
|
||||
* @return string
|
||||
*/
|
||||
protected function buildConnectString($driver, array $arguments)
|
||||
{
|
||||
return $driver.':'.implode(';', array_map(function ($key) use ($arguments) {
|
||||
return sprintf('%s=%s', $key, $arguments[$key]);
|
||||
}, array_keys($arguments)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a host string from the given configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @param string $separator
|
||||
* @return string
|
||||
*/
|
||||
protected function buildHostString(array $config, $separator)
|
||||
{
|
||||
if (empty($config['port'])) {
|
||||
return $config['host'];
|
||||
}
|
||||
|
||||
return $config['host'].$separator.$config['port'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the available PDO drivers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getAvailableDrivers()
|
||||
{
|
||||
return PDO::getAvailableDrivers();
|
||||
}
|
||||
}
|
108
vendor/illuminate/database/Console/Factories/FactoryMakeCommand.php
vendored
Normal file
108
vendor/illuminate/database/Console/Factories/FactoryMakeCommand.php
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Factories;
|
||||
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class FactoryMakeCommand extends GeneratorCommand
|
||||
{
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'make:factory';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create a new model factory';
|
||||
|
||||
/**
|
||||
* The type of class being generated.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'Factory';
|
||||
|
||||
/**
|
||||
* Get the stub file for the generator.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getStub()
|
||||
{
|
||||
return $this->resolveStubPath('/stubs/factory.stub');
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the fully-qualified path to the stub.
|
||||
*
|
||||
* @param string $stub
|
||||
* @return string
|
||||
*/
|
||||
protected function resolveStubPath($stub)
|
||||
{
|
||||
return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
|
||||
? $customPath
|
||||
: __DIR__.$stub;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the class with the given name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
protected function buildClass($name)
|
||||
{
|
||||
$namespaceModel = $this->option('model')
|
||||
? $this->qualifyClass($this->option('model'))
|
||||
: trim($this->rootNamespace(), '\\').'\\Model';
|
||||
|
||||
$model = class_basename($namespaceModel);
|
||||
|
||||
$replace = [
|
||||
'NamespacedDummyModel' => $namespaceModel,
|
||||
'{{ namespacedModel }}' => $namespaceModel,
|
||||
'{{namespacedModel}}' => $namespaceModel,
|
||||
'DummyModel' => $model,
|
||||
'{{ model }}' => $model,
|
||||
'{{model}}' => $model,
|
||||
];
|
||||
|
||||
return str_replace(
|
||||
array_keys($replace), array_values($replace), parent::buildClass($name)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the destination class path.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
protected function getPath($name)
|
||||
{
|
||||
$name = str_replace(
|
||||
['\\', '/'], '', $this->argument('name')
|
||||
);
|
||||
|
||||
return $this->laravel->databasePath()."/factories/{$name}.php";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['model', 'm', InputOption::VALUE_OPTIONAL, 'The name of the model'],
|
||||
];
|
||||
}
|
||||
}
|
12
vendor/illuminate/database/Console/Factories/stubs/factory.stub
vendored
Normal file
12
vendor/illuminate/database/Console/Factories/stubs/factory.stub
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Factory $factory */
|
||||
|
||||
use Faker\Generator as Faker;
|
||||
use {{ namespacedModel }};
|
||||
|
||||
$factory->define({{ model }}::class, function (Faker $faker) {
|
||||
return [
|
||||
//
|
||||
];
|
||||
});
|
51
vendor/illuminate/database/Console/Migrations/BaseCommand.php
vendored
Executable file
51
vendor/illuminate/database/Console/Migrations/BaseCommand.php
vendored
Executable file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class BaseCommand extends Command
|
||||
{
|
||||
/**
|
||||
* Get all of the migration paths.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getMigrationPaths()
|
||||
{
|
||||
// Here, we will check to see if a path option has been defined. If it has we will
|
||||
// use the path relative to the root of the installation folder so our database
|
||||
// migrations may be run for any customized path from within the application.
|
||||
if ($this->input->hasOption('path') && $this->option('path')) {
|
||||
return collect($this->option('path'))->map(function ($path) {
|
||||
return ! $this->usingRealPath()
|
||||
? $this->laravel->basePath().'/'.$path
|
||||
: $path;
|
||||
})->all();
|
||||
}
|
||||
|
||||
return array_merge(
|
||||
$this->migrator->paths(), [$this->getMigrationPath()]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given path(s) are pre-resolved "real" paths.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function usingRealPath()
|
||||
{
|
||||
return $this->input->hasOption('realpath') && $this->option('realpath');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to the migration directory.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getMigrationPath()
|
||||
{
|
||||
return $this->laravel->databasePath().DIRECTORY_SEPARATOR.'migrations';
|
||||
}
|
||||
}
|
106
vendor/illuminate/database/Console/Migrations/FreshCommand.php
vendored
Normal file
106
vendor/illuminate/database/Console/Migrations/FreshCommand.php
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class FreshCommand extends Command
|
||||
{
|
||||
use ConfirmableTrait;
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'migrate:fresh';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Drop all tables and re-run all migrations';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (! $this->confirmToProceed()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$database = $this->input->getOption('database');
|
||||
|
||||
$this->call('db:wipe', array_filter([
|
||||
'--database' => $database,
|
||||
'--drop-views' => $this->option('drop-views'),
|
||||
'--drop-types' => $this->option('drop-types'),
|
||||
'--force' => true,
|
||||
]));
|
||||
|
||||
$this->call('migrate', array_filter([
|
||||
'--database' => $database,
|
||||
'--path' => $this->input->getOption('path'),
|
||||
'--realpath' => $this->input->getOption('realpath'),
|
||||
'--force' => true,
|
||||
'--step' => $this->option('step'),
|
||||
]));
|
||||
|
||||
if ($this->needsSeeding()) {
|
||||
$this->runSeeder($database);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the developer has requested database seeding.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function needsSeeding()
|
||||
{
|
||||
return $this->option('seed') || $this->option('seeder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the database seeder command.
|
||||
*
|
||||
* @param string $database
|
||||
* @return void
|
||||
*/
|
||||
protected function runSeeder($database)
|
||||
{
|
||||
$this->call('db:seed', array_filter([
|
||||
'--database' => $database,
|
||||
'--class' => $this->option('seeder') ?: 'DatabaseSeeder',
|
||||
'--force' => true,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use'],
|
||||
['drop-views', null, InputOption::VALUE_NONE, 'Drop all tables and views'],
|
||||
['drop-types', null, InputOption::VALUE_NONE, 'Drop all tables and types (Postgres only)'],
|
||||
['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production'],
|
||||
['path', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The path(s) to the migrations files to be executed'],
|
||||
['realpath', null, InputOption::VALUE_NONE, 'Indicate any provided migration file paths are pre-resolved absolute paths'],
|
||||
['seed', null, InputOption::VALUE_NONE, 'Indicates if the seed task should be re-run'],
|
||||
['seeder', null, InputOption::VALUE_OPTIONAL, 'The class name of the root seeder'],
|
||||
['step', null, InputOption::VALUE_NONE, 'Force the migrations to be run so they can be rolled back individually'],
|
||||
];
|
||||
}
|
||||
}
|
70
vendor/illuminate/database/Console/Migrations/InstallCommand.php
vendored
Executable file
70
vendor/illuminate/database/Console/Migrations/InstallCommand.php
vendored
Executable file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\Migrations\MigrationRepositoryInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class InstallCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'migrate:install';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create the migration repository';
|
||||
|
||||
/**
|
||||
* The repository instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\MigrationRepositoryInterface
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* Create a new migration install command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\MigrationRepositoryInterface $repository
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(MigrationRepositoryInterface $repository)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->repository->setSource($this->input->getOption('database'));
|
||||
|
||||
$this->repository->createRepository();
|
||||
|
||||
$this->info('Migration table created successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use'],
|
||||
];
|
||||
}
|
||||
}
|
99
vendor/illuminate/database/Console/Migrations/MigrateCommand.php
vendored
Executable file
99
vendor/illuminate/database/Console/Migrations/MigrateCommand.php
vendored
Executable file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Illuminate\Database\Migrations\Migrator;
|
||||
|
||||
class MigrateCommand extends BaseCommand
|
||||
{
|
||||
use ConfirmableTrait;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'migrate {--database= : The database connection to use}
|
||||
{--force : Force the operation to run when in production}
|
||||
{--path=* : The path(s) to the migrations files to be executed}
|
||||
{--realpath : Indicate any provided migration file paths are pre-resolved absolute paths}
|
||||
{--pretend : Dump the SQL queries that would be run}
|
||||
{--seed : Indicates if the seed task should be re-run}
|
||||
{--step : Force the migrations to be run so they can be rolled back individually}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Run the database migrations';
|
||||
|
||||
/**
|
||||
* The migrator instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\Migrator
|
||||
*/
|
||||
protected $migrator;
|
||||
|
||||
/**
|
||||
* Create a new migration command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\Migrator $migrator
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Migrator $migrator)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->migrator = $migrator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (! $this->confirmToProceed()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$this->migrator->usingConnection($this->option('database'), function () {
|
||||
$this->prepareDatabase();
|
||||
|
||||
// Next, we will check to see if a path option has been defined. If it has
|
||||
// we will use the path relative to the root of this installation folder
|
||||
// so that migrations may be run for any path within the applications.
|
||||
$this->migrator->setOutput($this->output)
|
||||
->run($this->getMigrationPaths(), [
|
||||
'pretend' => $this->option('pretend'),
|
||||
'step' => $this->option('step'),
|
||||
]);
|
||||
|
||||
// Finally, if the "seed" option has been given, we will re-run the database
|
||||
// seed task to re-populate the database, which is convenient when adding
|
||||
// a migration and a seed at the same time, as it is only this command.
|
||||
if ($this->option('seed') && ! $this->option('pretend')) {
|
||||
$this->call('db:seed', ['--force' => true]);
|
||||
}
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the migration database for running.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function prepareDatabase()
|
||||
{
|
||||
if (! $this->migrator->repositoryExists()) {
|
||||
$this->call('migrate:install', array_filter([
|
||||
'--database' => $this->option('database'),
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
145
vendor/illuminate/database/Console/Migrations/MigrateMakeCommand.php
vendored
Normal file
145
vendor/illuminate/database/Console/Migrations/MigrateMakeCommand.php
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Database\Migrations\MigrationCreator;
|
||||
use Illuminate\Support\Composer;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class MigrateMakeCommand extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The console command signature.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'make:migration {name : The name of the migration}
|
||||
{--create= : The table to be created}
|
||||
{--table= : The table to migrate}
|
||||
{--path= : The location where the migration file should be created}
|
||||
{--realpath : Indicate any provided migration file paths are pre-resolved absolute paths}
|
||||
{--fullpath : Output the full path of the migration}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create a new migration file';
|
||||
|
||||
/**
|
||||
* The migration creator instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\MigrationCreator
|
||||
*/
|
||||
protected $creator;
|
||||
|
||||
/**
|
||||
* The Composer instance.
|
||||
*
|
||||
* @var \Illuminate\Support\Composer
|
||||
*/
|
||||
protected $composer;
|
||||
|
||||
/**
|
||||
* Create a new migration install command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\MigrationCreator $creator
|
||||
* @param \Illuminate\Support\Composer $composer
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(MigrationCreator $creator, Composer $composer)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->creator = $creator;
|
||||
$this->composer = $composer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// It's possible for the developer to specify the tables to modify in this
|
||||
// schema operation. The developer may also specify if this table needs
|
||||
// to be freshly created so we can create the appropriate migrations.
|
||||
$name = Str::snake(trim($this->input->getArgument('name')));
|
||||
|
||||
$table = $this->input->getOption('table');
|
||||
|
||||
$create = $this->input->getOption('create') ?: false;
|
||||
|
||||
// If no table was given as an option but a create option is given then we
|
||||
// will use the "create" option as the table name. This allows the devs
|
||||
// to pass a table name into this option as a short-cut for creating.
|
||||
if (! $table && is_string($create)) {
|
||||
$table = $create;
|
||||
|
||||
$create = true;
|
||||
}
|
||||
|
||||
// Next, we will attempt to guess the table name if this the migration has
|
||||
// "create" in the name. This will allow us to provide a convenient way
|
||||
// of creating migrations that create new tables for the application.
|
||||
if (! $table) {
|
||||
[$table, $create] = TableGuesser::guess($name);
|
||||
}
|
||||
|
||||
// Now we are ready to write the migration out to disk. Once we've written
|
||||
// the migration out, we will dump-autoload for the entire framework to
|
||||
// make sure that the migrations are registered by the class loaders.
|
||||
$this->writeMigration($name, $table, $create);
|
||||
|
||||
$this->composer->dumpAutoloads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the migration file to disk.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $table
|
||||
* @param bool $create
|
||||
* @return string
|
||||
*/
|
||||
protected function writeMigration($name, $table, $create)
|
||||
{
|
||||
$file = $this->creator->create(
|
||||
$name, $this->getMigrationPath(), $table, $create
|
||||
);
|
||||
|
||||
if (! $this->option('fullpath')) {
|
||||
$file = pathinfo($file, PATHINFO_FILENAME);
|
||||
}
|
||||
|
||||
$this->line("<info>Created Migration:</info> {$file}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get migration path (either specified by '--path' option or default location).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getMigrationPath()
|
||||
{
|
||||
if (! is_null($targetPath = $this->input->getOption('path'))) {
|
||||
return ! $this->usingRealPath()
|
||||
? $this->laravel->basePath().'/'.$targetPath
|
||||
: $targetPath;
|
||||
}
|
||||
|
||||
return parent::getMigrationPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given path(s) are pre-resolved "real" paths.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function usingRealPath()
|
||||
{
|
||||
return $this->input->hasOption('realpath') && $this->option('realpath');
|
||||
}
|
||||
}
|
151
vendor/illuminate/database/Console/Migrations/RefreshCommand.php
vendored
Executable file
151
vendor/illuminate/database/Console/Migrations/RefreshCommand.php
vendored
Executable file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class RefreshCommand extends Command
|
||||
{
|
||||
use ConfirmableTrait;
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'migrate:refresh';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Reset and re-run all migrations';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (! $this->confirmToProceed()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Next we'll gather some of the options so that we can have the right options
|
||||
// to pass to the commands. This includes options such as which database to
|
||||
// use and the path to use for the migration. Then we'll run the command.
|
||||
$database = $this->input->getOption('database');
|
||||
|
||||
$path = $this->input->getOption('path');
|
||||
|
||||
// If the "step" option is specified it means we only want to rollback a small
|
||||
// number of migrations before migrating again. For example, the user might
|
||||
// only rollback and remigrate the latest four migrations instead of all.
|
||||
$step = $this->input->getOption('step') ?: 0;
|
||||
|
||||
if ($step > 0) {
|
||||
$this->runRollback($database, $path, $step);
|
||||
} else {
|
||||
$this->runReset($database, $path);
|
||||
}
|
||||
|
||||
// The refresh command is essentially just a brief aggregate of a few other of
|
||||
// the migration commands and just provides a convenient wrapper to execute
|
||||
// them in succession. We'll also see if we need to re-seed the database.
|
||||
$this->call('migrate', array_filter([
|
||||
'--database' => $database,
|
||||
'--path' => $path,
|
||||
'--realpath' => $this->input->getOption('realpath'),
|
||||
'--force' => true,
|
||||
]));
|
||||
|
||||
if ($this->needsSeeding()) {
|
||||
$this->runSeeder($database);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the rollback command.
|
||||
*
|
||||
* @param string $database
|
||||
* @param string $path
|
||||
* @param int $step
|
||||
* @return void
|
||||
*/
|
||||
protected function runRollback($database, $path, $step)
|
||||
{
|
||||
$this->call('migrate:rollback', array_filter([
|
||||
'--database' => $database,
|
||||
'--path' => $path,
|
||||
'--realpath' => $this->input->getOption('realpath'),
|
||||
'--step' => $step,
|
||||
'--force' => true,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the reset command.
|
||||
*
|
||||
* @param string $database
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
protected function runReset($database, $path)
|
||||
{
|
||||
$this->call('migrate:reset', array_filter([
|
||||
'--database' => $database,
|
||||
'--path' => $path,
|
||||
'--realpath' => $this->input->getOption('realpath'),
|
||||
'--force' => true,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the developer has requested database seeding.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function needsSeeding()
|
||||
{
|
||||
return $this->option('seed') || $this->option('seeder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the database seeder command.
|
||||
*
|
||||
* @param string $database
|
||||
* @return void
|
||||
*/
|
||||
protected function runSeeder($database)
|
||||
{
|
||||
$this->call('db:seed', array_filter([
|
||||
'--database' => $database,
|
||||
'--class' => $this->option('seeder') ?: 'DatabaseSeeder',
|
||||
'--force' => true,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use'],
|
||||
['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production'],
|
||||
['path', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The path(s) to the migrations files to be executed'],
|
||||
['realpath', null, InputOption::VALUE_NONE, 'Indicate any provided migration file paths are pre-resolved absolute paths'],
|
||||
['seed', null, InputOption::VALUE_NONE, 'Indicates if the seed task should be re-run'],
|
||||
['seeder', null, InputOption::VALUE_OPTIONAL, 'The class name of the root seeder'],
|
||||
['step', null, InputOption::VALUE_OPTIONAL, 'The number of migrations to be reverted & re-run'],
|
||||
];
|
||||
}
|
||||
}
|
93
vendor/illuminate/database/Console/Migrations/ResetCommand.php
vendored
Executable file
93
vendor/illuminate/database/Console/Migrations/ResetCommand.php
vendored
Executable file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Illuminate\Database\Migrations\Migrator;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class ResetCommand extends BaseCommand
|
||||
{
|
||||
use ConfirmableTrait;
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'migrate:reset';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Rollback all database migrations';
|
||||
|
||||
/**
|
||||
* The migrator instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\Migrator
|
||||
*/
|
||||
protected $migrator;
|
||||
|
||||
/**
|
||||
* Create a new migration rollback command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\Migrator $migrator
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Migrator $migrator)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->migrator = $migrator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (! $this->confirmToProceed()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return $this->migrator->usingConnection($this->option('database'), function () {
|
||||
// First, we'll make sure that the migration table actually exists before we
|
||||
// start trying to rollback and re-run all of the migrations. If it's not
|
||||
// present we'll just bail out with an info message for the developers.
|
||||
if (! $this->migrator->repositoryExists()) {
|
||||
return $this->comment('Migration table not found.');
|
||||
}
|
||||
|
||||
$this->migrator->setOutput($this->output)->reset(
|
||||
$this->getMigrationPaths(), $this->option('pretend')
|
||||
);
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use'],
|
||||
|
||||
['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production'],
|
||||
|
||||
['path', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The path(s) to the migrations files to be executed'],
|
||||
|
||||
['realpath', null, InputOption::VALUE_NONE, 'Indicate any provided migration file paths are pre-resolved absolute paths'],
|
||||
|
||||
['pretend', null, InputOption::VALUE_NONE, 'Dump the SQL queries that would be run'],
|
||||
];
|
||||
}
|
||||
}
|
91
vendor/illuminate/database/Console/Migrations/RollbackCommand.php
vendored
Executable file
91
vendor/illuminate/database/Console/Migrations/RollbackCommand.php
vendored
Executable file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Illuminate\Database\Migrations\Migrator;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class RollbackCommand extends BaseCommand
|
||||
{
|
||||
use ConfirmableTrait;
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'migrate:rollback';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Rollback the last database migration';
|
||||
|
||||
/**
|
||||
* The migrator instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\Migrator
|
||||
*/
|
||||
protected $migrator;
|
||||
|
||||
/**
|
||||
* Create a new migration rollback command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\Migrator $migrator
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Migrator $migrator)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->migrator = $migrator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (! $this->confirmToProceed()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$this->migrator->usingConnection($this->option('database'), function () {
|
||||
$this->migrator->setOutput($this->output)->rollback(
|
||||
$this->getMigrationPaths(), [
|
||||
'pretend' => $this->option('pretend'),
|
||||
'step' => (int) $this->option('step'),
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use'],
|
||||
|
||||
['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production'],
|
||||
|
||||
['path', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The path(s) to the migrations files to be executed'],
|
||||
|
||||
['realpath', null, InputOption::VALUE_NONE, 'Indicate any provided migration file paths are pre-resolved absolute paths'],
|
||||
|
||||
['pretend', null, InputOption::VALUE_NONE, 'Dump the SQL queries that would be run'],
|
||||
|
||||
['step', null, InputOption::VALUE_OPTIONAL, 'The number of migrations to be reverted'],
|
||||
];
|
||||
}
|
||||
}
|
115
vendor/illuminate/database/Console/Migrations/StatusCommand.php
vendored
Normal file
115
vendor/illuminate/database/Console/Migrations/StatusCommand.php
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Database\Migrations\Migrator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class StatusCommand extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'migrate:status';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Show the status of each migration';
|
||||
|
||||
/**
|
||||
* The migrator instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\Migrator
|
||||
*/
|
||||
protected $migrator;
|
||||
|
||||
/**
|
||||
* Create a new migration rollback command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\Migrator $migrator
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Migrator $migrator)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->migrator = $migrator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
return $this->migrator->usingConnection($this->option('database'), function () {
|
||||
if (! $this->migrator->repositoryExists()) {
|
||||
$this->error('Migration table not found.');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$ran = $this->migrator->getRepository()->getRan();
|
||||
|
||||
$batches = $this->migrator->getRepository()->getMigrationBatches();
|
||||
|
||||
if (count($migrations = $this->getStatusFor($ran, $batches)) > 0) {
|
||||
$this->table(['Ran?', 'Migration', 'Batch'], $migrations);
|
||||
} else {
|
||||
$this->error('No migrations found');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the status for the given ran migrations.
|
||||
*
|
||||
* @param array $ran
|
||||
* @param array $batches
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function getStatusFor(array $ran, array $batches)
|
||||
{
|
||||
return Collection::make($this->getAllMigrationFiles())
|
||||
->map(function ($migration) use ($ran, $batches) {
|
||||
$migrationName = $this->migrator->getMigrationName($migration);
|
||||
|
||||
return in_array($migrationName, $ran)
|
||||
? ['<info>Yes</info>', $migrationName, $batches[$migrationName]]
|
||||
: ['<fg=red>No</fg=red>', $migrationName];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all of the migration files.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getAllMigrationFiles()
|
||||
{
|
||||
return $this->migrator->getMigrationFiles($this->getMigrationPaths());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use'],
|
||||
|
||||
['path', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The path(s) to the migrations files to use'],
|
||||
|
||||
['realpath', null, InputOption::VALUE_NONE, 'Indicate any provided migration file paths are pre-resolved absolute paths'],
|
||||
];
|
||||
}
|
||||
}
|
37
vendor/illuminate/database/Console/Migrations/TableGuesser.php
vendored
Normal file
37
vendor/illuminate/database/Console/Migrations/TableGuesser.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
class TableGuesser
|
||||
{
|
||||
const CREATE_PATTERNS = [
|
||||
'/^create_(\w+)_table$/',
|
||||
'/^create_(\w+)$/',
|
||||
];
|
||||
|
||||
const CHANGE_PATTERNS = [
|
||||
'/_(to|from|in)_(\w+)_table$/',
|
||||
'/_(to|from|in)_(\w+)$/',
|
||||
];
|
||||
|
||||
/**
|
||||
* Attempt to guess the table name and "creation" status of the given migration.
|
||||
*
|
||||
* @param string $migration
|
||||
* @return array
|
||||
*/
|
||||
public static function guess($migration)
|
||||
{
|
||||
foreach (self::CREATE_PATTERNS as $pattern) {
|
||||
if (preg_match($pattern, $migration, $matches)) {
|
||||
return [$matches[1], $create = true];
|
||||
}
|
||||
}
|
||||
|
||||
foreach (self::CHANGE_PATTERNS as $pattern) {
|
||||
if (preg_match($pattern, $migration, $matches)) {
|
||||
return [$matches[2], $create = false];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
116
vendor/illuminate/database/Console/Seeds/SeedCommand.php
vendored
Normal file
116
vendor/illuminate/database/Console/Seeds/SeedCommand.php
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Seeds;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Illuminate\Database\ConnectionResolverInterface as Resolver;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class SeedCommand extends Command
|
||||
{
|
||||
use ConfirmableTrait;
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'db:seed';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Seed the database with records';
|
||||
|
||||
/**
|
||||
* The connection resolver instance.
|
||||
*
|
||||
* @var \Illuminate\Database\ConnectionResolverInterface
|
||||
*/
|
||||
protected $resolver;
|
||||
|
||||
/**
|
||||
* Create a new database seed command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\ConnectionResolverInterface $resolver
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Resolver $resolver)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->resolver = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (! $this->confirmToProceed()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$previousConnection = $this->resolver->getDefaultConnection();
|
||||
|
||||
$this->resolver->setDefaultConnection($this->getDatabase());
|
||||
|
||||
Model::unguarded(function () {
|
||||
$this->getSeeder()->__invoke();
|
||||
});
|
||||
|
||||
if ($previousConnection) {
|
||||
$this->resolver->setDefaultConnection($previousConnection);
|
||||
}
|
||||
|
||||
$this->info('Database seeding completed successfully.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a seeder instance from the container.
|
||||
*
|
||||
* @return \Illuminate\Database\Seeder
|
||||
*/
|
||||
protected function getSeeder()
|
||||
{
|
||||
$class = $this->laravel->make($this->input->getOption('class'));
|
||||
|
||||
return $class->setContainer($this->laravel)->setCommand($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the database connection to use.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getDatabase()
|
||||
{
|
||||
$database = $this->input->getOption('database');
|
||||
|
||||
return $database ?: $this->laravel['config']['database.default'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['class', null, InputOption::VALUE_OPTIONAL, 'The class name of the root seeder', 'DatabaseSeeder'],
|
||||
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to seed'],
|
||||
|
||||
['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production'],
|
||||
];
|
||||
}
|
||||
}
|
109
vendor/illuminate/database/Console/Seeds/SeederMakeCommand.php
vendored
Normal file
109
vendor/illuminate/database/Console/Seeds/SeederMakeCommand.php
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Seeds;
|
||||
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Composer;
|
||||
|
||||
class SeederMakeCommand extends GeneratorCommand
|
||||
{
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'make:seeder';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create a new seeder class';
|
||||
|
||||
/**
|
||||
* The type of class being generated.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'Seeder';
|
||||
|
||||
/**
|
||||
* The Composer instance.
|
||||
*
|
||||
* @var \Illuminate\Support\Composer
|
||||
*/
|
||||
protected $composer;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @param \Illuminate\Filesystem\Filesystem $files
|
||||
* @param \Illuminate\Support\Composer $composer
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Filesystem $files, Composer $composer)
|
||||
{
|
||||
parent::__construct($files);
|
||||
|
||||
$this->composer = $composer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
parent::handle();
|
||||
|
||||
$this->composer->dumpAutoloads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stub file for the generator.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getStub()
|
||||
{
|
||||
return $this->resolveStubPath('/stubs/seeder.stub');
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the fully-qualified path to the stub.
|
||||
*
|
||||
* @param string $stub
|
||||
* @return string
|
||||
*/
|
||||
protected function resolveStubPath($stub)
|
||||
{
|
||||
return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
|
||||
? $customPath
|
||||
: __DIR__.$stub;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the destination class path.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
protected function getPath($name)
|
||||
{
|
||||
return $this->laravel->databasePath().'/seeds/'.$name.'.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the class name and format according to the root namespace.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
protected function qualifyClass($name)
|
||||
{
|
||||
return $name;
|
||||
}
|
||||
}
|
16
vendor/illuminate/database/Console/Seeds/stubs/seeder.stub
vendored
Normal file
16
vendor/illuminate/database/Console/Seeds/stubs/seeder.stub
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class {{ class }} extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
112
vendor/illuminate/database/Console/WipeCommand.php
vendored
Normal file
112
vendor/illuminate/database/Console/WipeCommand.php
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class WipeCommand extends Command
|
||||
{
|
||||
use ConfirmableTrait;
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'db:wipe';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Drop all tables, views, and types';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (! $this->confirmToProceed()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$database = $this->input->getOption('database');
|
||||
|
||||
if ($this->option('drop-views')) {
|
||||
$this->dropAllViews($database);
|
||||
|
||||
$this->info('Dropped all views successfully.');
|
||||
}
|
||||
|
||||
$this->dropAllTables($database);
|
||||
|
||||
$this->info('Dropped all tables successfully.');
|
||||
|
||||
if ($this->option('drop-types')) {
|
||||
$this->dropAllTypes($database);
|
||||
|
||||
$this->info('Dropped all types successfully.');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all of the database tables.
|
||||
*
|
||||
* @param string $database
|
||||
* @return void
|
||||
*/
|
||||
protected function dropAllTables($database)
|
||||
{
|
||||
$this->laravel['db']->connection($database)
|
||||
->getSchemaBuilder()
|
||||
->dropAllTables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all of the database views.
|
||||
*
|
||||
* @param string $database
|
||||
* @return void
|
||||
*/
|
||||
protected function dropAllViews($database)
|
||||
{
|
||||
$this->laravel['db']->connection($database)
|
||||
->getSchemaBuilder()
|
||||
->dropAllViews();
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all of the database types.
|
||||
*
|
||||
* @param string $database
|
||||
* @return void
|
||||
*/
|
||||
protected function dropAllTypes($database)
|
||||
{
|
||||
$this->laravel['db']->connection($database)
|
||||
->getSchemaBuilder()
|
||||
->dropAllTypes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use'],
|
||||
['drop-views', null, InputOption::VALUE_NONE, 'Drop all tables and views'],
|
||||
['drop-types', null, InputOption::VALUE_NONE, 'Drop all tables and types (Postgres only)'],
|
||||
['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production'],
|
||||
];
|
||||
}
|
||||
}
|
369
vendor/illuminate/database/DatabaseManager.php
vendored
Executable file
369
vendor/illuminate/database/DatabaseManager.php
vendored
Executable file
@ -0,0 +1,369 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Illuminate\Database\Connectors\ConnectionFactory;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\ConfigurationUrlParser;
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
* @mixin \Illuminate\Database\Connection
|
||||
*/
|
||||
class DatabaseManager implements ConnectionResolverInterface
|
||||
{
|
||||
/**
|
||||
* The application instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Foundation\Application
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* The database connection factory instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connectors\ConnectionFactory
|
||||
*/
|
||||
protected $factory;
|
||||
|
||||
/**
|
||||
* The active connection instances.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $connections = [];
|
||||
|
||||
/**
|
||||
* The custom connection resolvers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $extensions = [];
|
||||
|
||||
/**
|
||||
* The callback to be executed to reconnect to a database.
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
protected $reconnector;
|
||||
|
||||
/**
|
||||
* Create a new database manager instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Foundation\Application $app
|
||||
* @param \Illuminate\Database\Connectors\ConnectionFactory $factory
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($app, ConnectionFactory $factory)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->factory = $factory;
|
||||
|
||||
$this->reconnector = function ($connection) {
|
||||
$this->reconnect($connection->getName());
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a database connection instance.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public function connection($name = null)
|
||||
{
|
||||
[$database, $type] = $this->parseConnectionName($name);
|
||||
|
||||
$name = $name ?: $database;
|
||||
|
||||
// If we haven't created this connection, we'll create it based on the config
|
||||
// provided in the application. Once we've created the connections we will
|
||||
// set the "fetch mode" for PDO which determines the query return types.
|
||||
if (! isset($this->connections[$name])) {
|
||||
$this->connections[$name] = $this->configure(
|
||||
$this->makeConnection($database), $type
|
||||
);
|
||||
}
|
||||
|
||||
return $this->connections[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the connection into an array of the name and read / write type.
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
protected function parseConnectionName($name)
|
||||
{
|
||||
$name = $name ?: $this->getDefaultConnection();
|
||||
|
||||
return Str::endsWith($name, ['::read', '::write'])
|
||||
? explode('::', $name, 2) : [$name, null];
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the database connection instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
protected function makeConnection($name)
|
||||
{
|
||||
$config = $this->configuration($name);
|
||||
|
||||
// First we will check by the connection name to see if an extension has been
|
||||
// registered specifically for that connection. If it has we will call the
|
||||
// Closure and pass it the config allowing it to resolve the connection.
|
||||
if (isset($this->extensions[$name])) {
|
||||
return call_user_func($this->extensions[$name], $config, $name);
|
||||
}
|
||||
|
||||
// Next we will check to see if an extension has been registered for a driver
|
||||
// and will call the Closure if so, which allows us to have a more generic
|
||||
// resolver for the drivers themselves which applies to all connections.
|
||||
if (isset($this->extensions[$driver = $config['driver']])) {
|
||||
return call_user_func($this->extensions[$driver], $config, $name);
|
||||
}
|
||||
|
||||
return $this->factory->make($config, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration for a connection.
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function configuration($name)
|
||||
{
|
||||
$name = $name ?: $this->getDefaultConnection();
|
||||
|
||||
// To get the database connection configuration, we will just pull each of the
|
||||
// connection configurations and get the configurations for the given name.
|
||||
// If the configuration doesn't exist, we'll throw an exception and bail.
|
||||
$connections = $this->app['config']['database.connections'];
|
||||
|
||||
if (is_null($config = Arr::get($connections, $name))) {
|
||||
throw new InvalidArgumentException("Database connection [{$name}] not configured.");
|
||||
}
|
||||
|
||||
return (new ConfigurationUrlParser)
|
||||
->parseConfiguration($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the database connection instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param string $type
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
protected function configure(Connection $connection, $type)
|
||||
{
|
||||
$connection = $this->setPdoForType($connection, $type);
|
||||
|
||||
// First we'll set the fetch mode and a few other dependencies of the database
|
||||
// connection. This method basically just configures and prepares it to get
|
||||
// used by the application. Once we're finished we'll return it back out.
|
||||
if ($this->app->bound('events')) {
|
||||
$connection->setEventDispatcher($this->app['events']);
|
||||
}
|
||||
|
||||
// Here we'll set a reconnector callback. This reconnector can be any callable
|
||||
// so we will set a Closure to reconnect from this manager with the name of
|
||||
// the connection, which will allow us to reconnect from the connections.
|
||||
$connection->setReconnector($this->reconnector);
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the read / write mode for database connection instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param string|null $type
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
protected function setPdoForType(Connection $connection, $type = null)
|
||||
{
|
||||
if ($type === 'read') {
|
||||
$connection->setPdo($connection->getReadPdo());
|
||||
} elseif ($type === 'write') {
|
||||
$connection->setReadPdo($connection->getPdo());
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the given database and remove from local cache.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @return void
|
||||
*/
|
||||
public function purge($name = null)
|
||||
{
|
||||
$name = $name ?: $this->getDefaultConnection();
|
||||
|
||||
$this->disconnect($name);
|
||||
|
||||
unset($this->connections[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the given database.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect($name = null)
|
||||
{
|
||||
if (isset($this->connections[$name = $name ?: $this->getDefaultConnection()])) {
|
||||
$this->connections[$name]->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconnect to the given database.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public function reconnect($name = null)
|
||||
{
|
||||
$this->disconnect($name = $name ?: $this->getDefaultConnection());
|
||||
|
||||
if (! isset($this->connections[$name])) {
|
||||
return $this->connection($name);
|
||||
}
|
||||
|
||||
return $this->refreshPdoConnections($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default database connection for the callback execution.
|
||||
*
|
||||
* @param string $name
|
||||
* @param callable $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function usingConnection($name, callable $callback)
|
||||
{
|
||||
$previousName = $this->getDefaultConnection();
|
||||
|
||||
$this->setDefaultConnection($name);
|
||||
|
||||
return tap($callback(), function () use ($previousName) {
|
||||
$this->setDefaultConnection($previousName);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the PDO connections on a given connection.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
protected function refreshPdoConnections($name)
|
||||
{
|
||||
$fresh = $this->makeConnection($name);
|
||||
|
||||
return $this->connections[$name]
|
||||
->setPdo($fresh->getRawPdo())
|
||||
->setReadPdo($fresh->getRawReadPdo());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default connection name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultConnection()
|
||||
{
|
||||
return $this->app['config']['database.default'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default connection name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaultConnection($name)
|
||||
{
|
||||
$this->app['config']['database.default'] = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the support drivers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function supportedDrivers()
|
||||
{
|
||||
return ['mysql', 'pgsql', 'sqlite', 'sqlsrv'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the drivers that are actually available.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function availableDrivers()
|
||||
{
|
||||
return array_intersect(
|
||||
$this->supportedDrivers(),
|
||||
str_replace('dblib', 'sqlsrv', PDO::getAvailableDrivers())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an extension connection resolver.
|
||||
*
|
||||
* @param string $name
|
||||
* @param callable $resolver
|
||||
* @return void
|
||||
*/
|
||||
public function extend($name, callable $resolver)
|
||||
{
|
||||
$this->extensions[$name] = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all of the created connections.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getConnections()
|
||||
{
|
||||
return $this->connections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database reconnector callback.
|
||||
*
|
||||
* @param callable $reconnector
|
||||
* @return void
|
||||
*/
|
||||
public function setReconnector(callable $reconnector)
|
||||
{
|
||||
$this->reconnector = $reconnector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically pass methods to the default connection.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
return $this->connection()->$method(...$parameters);
|
||||
}
|
||||
}
|
114
vendor/illuminate/database/DatabaseServiceProvider.php
vendored
Executable file
114
vendor/illuminate/database/DatabaseServiceProvider.php
vendored
Executable file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Faker\Factory as FakerFactory;
|
||||
use Faker\Generator as FakerGenerator;
|
||||
use Illuminate\Contracts\Queue\EntityResolver;
|
||||
use Illuminate\Database\Connectors\ConnectionFactory;
|
||||
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\QueueEntityResolver;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class DatabaseServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The array of resolved Faker instances.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $fakers = [];
|
||||
|
||||
/**
|
||||
* Bootstrap the application events.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
Model::setConnectionResolver($this->app['db']);
|
||||
|
||||
Model::setEventDispatcher($this->app['events']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
Model::clearBootedModels();
|
||||
|
||||
$this->registerConnectionServices();
|
||||
|
||||
$this->registerEloquentFactory();
|
||||
|
||||
$this->registerQueueableEntityResolver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the primary database bindings.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerConnectionServices()
|
||||
{
|
||||
// The connection factory is used to create the actual connection instances on
|
||||
// the database. We will inject the factory into the manager so that it may
|
||||
// make the connections while they are actually needed and not of before.
|
||||
$this->app->singleton('db.factory', function ($app) {
|
||||
return new ConnectionFactory($app);
|
||||
});
|
||||
|
||||
// The database manager is used to resolve various connections, since multiple
|
||||
// connections might be managed. It also implements the connection resolver
|
||||
// interface which may be used by other components requiring connections.
|
||||
$this->app->singleton('db', function ($app) {
|
||||
return new DatabaseManager($app, $app['db.factory']);
|
||||
});
|
||||
|
||||
$this->app->bind('db.connection', function ($app) {
|
||||
return $app['db']->connection();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Eloquent factory instance in the container.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerEloquentFactory()
|
||||
{
|
||||
$this->app->singleton(FakerGenerator::class, function ($app, $parameters) {
|
||||
$locale = $parameters['locale'] ?? $app['config']->get('app.faker_locale', 'en_US');
|
||||
|
||||
if (! isset(static::$fakers[$locale])) {
|
||||
static::$fakers[$locale] = FakerFactory::create($locale);
|
||||
}
|
||||
|
||||
static::$fakers[$locale]->unique(true);
|
||||
|
||||
return static::$fakers[$locale];
|
||||
});
|
||||
|
||||
$this->app->singleton(EloquentFactory::class, function ($app) {
|
||||
return EloquentFactory::construct(
|
||||
$app->make(FakerGenerator::class), $this->app->databasePath('factories')
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the queueable entity resolver implementation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerQueueableEntityResolver()
|
||||
{
|
||||
$this->app->singleton(EntityResolver::class, function () {
|
||||
return new QueueEntityResolver;
|
||||
});
|
||||
}
|
||||
}
|
37
vendor/illuminate/database/DetectsConcurrencyErrors.php
vendored
Normal file
37
vendor/illuminate/database/DetectsConcurrencyErrors.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use PDOException;
|
||||
use Throwable;
|
||||
|
||||
trait DetectsConcurrencyErrors
|
||||
{
|
||||
/**
|
||||
* Determine if the given exception was caused by a concurrency error such as a deadlock or serialization failure.
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @return bool
|
||||
*/
|
||||
protected function causedByConcurrencyError(Throwable $e)
|
||||
{
|
||||
if ($e instanceof PDOException && $e->getCode() === '40001') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$message = $e->getMessage();
|
||||
|
||||
return Str::contains($message, [
|
||||
'Deadlock found when trying to get lock',
|
||||
'deadlock detected',
|
||||
'The database file is locked',
|
||||
'database is locked',
|
||||
'database table is locked',
|
||||
'A table in the database is locked',
|
||||
'has been chosen as the deadlock victim',
|
||||
'Lock wait timeout exceeded; try restarting transaction',
|
||||
'WSREP detected deadlock/conflict and aborted the transaction. Try restarting the transaction',
|
||||
]);
|
||||
}
|
||||
}
|
55
vendor/illuminate/database/DetectsLostConnections.php
vendored
Normal file
55
vendor/illuminate/database/DetectsLostConnections.php
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Throwable;
|
||||
|
||||
trait DetectsLostConnections
|
||||
{
|
||||
/**
|
||||
* Determine if the given exception was caused by a lost connection.
|
||||
*
|
||||
* @param \Throwable $e
|
||||
* @return bool
|
||||
*/
|
||||
protected function causedByLostConnection(Throwable $e)
|
||||
{
|
||||
$message = $e->getMessage();
|
||||
|
||||
return Str::contains($message, [
|
||||
'server has gone away',
|
||||
'no connection to the server',
|
||||
'Lost connection',
|
||||
'is dead or not enabled',
|
||||
'Error while sending',
|
||||
'decryption failed or bad record mac',
|
||||
'server closed the connection unexpectedly',
|
||||
'SSL connection has been closed unexpectedly',
|
||||
'Error writing data to the connection',
|
||||
'Resource deadlock avoided',
|
||||
'Transaction() on null',
|
||||
'child connection forced to terminate due to client_idle_limit',
|
||||
'query_wait_timeout',
|
||||
'reset by peer',
|
||||
'Physical connection is not usable',
|
||||
'TCP Provider: Error code 0x68',
|
||||
'ORA-03114',
|
||||
'Packets out of order. Expected',
|
||||
'Adaptive Server connection failed',
|
||||
'Communication link failure',
|
||||
'connection is no longer usable',
|
||||
'Login timeout expired',
|
||||
'SQLSTATE[HY000] [2002] Connection refused',
|
||||
'running with the --read-only option so it cannot execute this statement',
|
||||
'The connection is broken and recovery is not possible. The connection is marked by the client driver as unrecoverable. No attempt was made to restore the connection.',
|
||||
'SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: Try again',
|
||||
'SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: Name or service not known',
|
||||
'SQLSTATE[HY000]: General error: 7 SSL SYSCALL error: EOF detected',
|
||||
'SQLSTATE[HY000] [2002] Connection timed out',
|
||||
'SSL: Connection timed out',
|
||||
'SQLSTATE[HY000]: General error: 1105 The last transaction was aborted due to Seamless Scaling. Please retry.',
|
||||
'Temporary failure in name resolution',
|
||||
]);
|
||||
}
|
||||
}
|
1495
vendor/illuminate/database/Eloquent/Builder.php
vendored
Executable file
1495
vendor/illuminate/database/Eloquent/Builder.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
674
vendor/illuminate/database/Eloquent/Collection.php
vendored
Executable file
674
vendor/illuminate/database/Eloquent/Collection.php
vendored
Executable file
@ -0,0 +1,674 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use Illuminate\Contracts\Queue\QueueableCollection;
|
||||
use Illuminate\Contracts\Queue\QueueableEntity;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection as BaseCollection;
|
||||
use Illuminate\Support\Str;
|
||||
use LogicException;
|
||||
|
||||
class Collection extends BaseCollection implements QueueableCollection
|
||||
{
|
||||
/**
|
||||
* Find a model in the collection by key.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $default
|
||||
* @return \Illuminate\Database\Eloquent\Model|static|null
|
||||
*/
|
||||
public function find($key, $default = null)
|
||||
{
|
||||
if ($key instanceof Model) {
|
||||
$key = $key->getKey();
|
||||
}
|
||||
|
||||
if ($key instanceof Arrayable) {
|
||||
$key = $key->toArray();
|
||||
}
|
||||
|
||||
if (is_array($key)) {
|
||||
if ($this->isEmpty()) {
|
||||
return new static;
|
||||
}
|
||||
|
||||
return $this->whereIn($this->first()->getKeyName(), $key);
|
||||
}
|
||||
|
||||
return Arr::first($this->items, function ($model) use ($key) {
|
||||
return $model->getKey() == $key;
|
||||
}, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of relationships onto the collection.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function load($relations)
|
||||
{
|
||||
if ($this->isNotEmpty()) {
|
||||
if (is_string($relations)) {
|
||||
$relations = func_get_args();
|
||||
}
|
||||
|
||||
$query = $this->first()->newQueryWithoutRelationships()->with($relations);
|
||||
|
||||
$this->items = $query->eagerLoadRelations($this->items);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of relationship counts onto the collection.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function loadCount($relations)
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$models = $this->first()->newModelQuery()
|
||||
->whereKey($this->modelKeys())
|
||||
->select($this->first()->getKeyName())
|
||||
->withCount(...func_get_args())
|
||||
->get()
|
||||
->keyBy($this->first()->getKeyName());
|
||||
|
||||
$attributes = Arr::except(
|
||||
array_keys($models->first()->getAttributes()),
|
||||
$models->first()->getKeyName()
|
||||
);
|
||||
|
||||
$this->each(function ($model) use ($models, $attributes) {
|
||||
$extraAttributes = Arr::only($models->get($model->getKey())->getAttributes(), $attributes);
|
||||
|
||||
$model->forceFill($extraAttributes)->syncOriginalAttributes($attributes);
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of relationships onto the collection if they are not already eager loaded.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function loadMissing($relations)
|
||||
{
|
||||
if (is_string($relations)) {
|
||||
$relations = func_get_args();
|
||||
}
|
||||
|
||||
foreach ($relations as $key => $value) {
|
||||
if (is_numeric($key)) {
|
||||
$key = $value;
|
||||
}
|
||||
|
||||
$segments = explode('.', explode(':', $key)[0]);
|
||||
|
||||
if (Str::contains($key, ':')) {
|
||||
$segments[count($segments) - 1] .= ':'.explode(':', $key)[1];
|
||||
}
|
||||
|
||||
$path = [];
|
||||
|
||||
foreach ($segments as $segment) {
|
||||
$path[] = [$segment => $segment];
|
||||
}
|
||||
|
||||
if (is_callable($value)) {
|
||||
$path[count($segments) - 1][end($segments)] = $value;
|
||||
}
|
||||
|
||||
$this->loadMissingRelation($this, $path);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a relationship path if it is not already eager loaded.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Collection $models
|
||||
* @param array $path
|
||||
* @return void
|
||||
*/
|
||||
protected function loadMissingRelation(self $models, array $path)
|
||||
{
|
||||
$relation = array_shift($path);
|
||||
|
||||
$name = explode(':', key($relation))[0];
|
||||
|
||||
if (is_string(reset($relation))) {
|
||||
$relation = reset($relation);
|
||||
}
|
||||
|
||||
$models->filter(function ($model) use ($name) {
|
||||
return ! is_null($model) && ! $model->relationLoaded($name);
|
||||
})->load($relation);
|
||||
|
||||
if (empty($path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$models = $models->pluck($name);
|
||||
|
||||
if ($models->first() instanceof BaseCollection) {
|
||||
$models = $models->collapse();
|
||||
}
|
||||
|
||||
$this->loadMissingRelation(new static($models), $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of relationships onto the mixed relationship collection.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param array $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function loadMorph($relation, $relations)
|
||||
{
|
||||
$this->pluck($relation)
|
||||
->filter()
|
||||
->groupBy(function ($model) {
|
||||
return get_class($model);
|
||||
})
|
||||
->each(function ($models, $className) use ($relations) {
|
||||
static::make($models)->load($relations[$className] ?? []);
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of relationship counts onto the mixed relationship collection.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param array $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function loadMorphCount($relation, $relations)
|
||||
{
|
||||
$this->pluck($relation)
|
||||
->filter()
|
||||
->groupBy(function ($model) {
|
||||
return get_class($model);
|
||||
})
|
||||
->each(function ($models, $className) use ($relations) {
|
||||
static::make($models)->loadCount($relations[$className] ?? []);
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a key exists in the collection.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function contains($key, $operator = null, $value = null)
|
||||
{
|
||||
if (func_num_args() > 1 || $this->useAsCallable($key)) {
|
||||
return parent::contains(...func_get_args());
|
||||
}
|
||||
|
||||
if ($key instanceof Model) {
|
||||
return parent::contains(function ($model) use ($key) {
|
||||
return $model->is($key);
|
||||
});
|
||||
}
|
||||
|
||||
return parent::contains(function ($model) use ($key) {
|
||||
return $model->getKey() == $key;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array of primary keys.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function modelKeys()
|
||||
{
|
||||
return array_map(function ($model) {
|
||||
return $model->getKey();
|
||||
}, $this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the collection with the given items.
|
||||
*
|
||||
* @param \ArrayAccess|array $items
|
||||
* @return static
|
||||
*/
|
||||
public function merge($items)
|
||||
{
|
||||
$dictionary = $this->getDictionary();
|
||||
|
||||
foreach ($items as $item) {
|
||||
$dictionary[$item->getKey()] = $item;
|
||||
}
|
||||
|
||||
return new static(array_values($dictionary));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a map over each of the items.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return \Illuminate\Support\Collection|static
|
||||
*/
|
||||
public function map(callable $callback)
|
||||
{
|
||||
$result = parent::map($callback);
|
||||
|
||||
return $result->contains(function ($item) {
|
||||
return ! $item instanceof Model;
|
||||
}) ? $result->toBase() : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an associative map over each of the items.
|
||||
*
|
||||
* The callback should return an associative array with a single key / value pair.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return \Illuminate\Support\Collection|static
|
||||
*/
|
||||
public function mapWithKeys(callable $callback)
|
||||
{
|
||||
$result = parent::mapWithKeys($callback);
|
||||
|
||||
return $result->contains(function ($item) {
|
||||
return ! $item instanceof Model;
|
||||
}) ? $result->toBase() : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload a fresh model instance from the database for all the entities.
|
||||
*
|
||||
* @param array|string $with
|
||||
* @return static
|
||||
*/
|
||||
public function fresh($with = [])
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
return new static;
|
||||
}
|
||||
|
||||
$model = $this->first();
|
||||
|
||||
$freshModels = $model->newQueryWithoutScopes()
|
||||
->with(is_string($with) ? func_get_args() : $with)
|
||||
->whereIn($model->getKeyName(), $this->modelKeys())
|
||||
->get()
|
||||
->getDictionary();
|
||||
|
||||
return $this->map(function ($model) use ($freshModels) {
|
||||
return $model->exists && isset($freshModels[$model->getKey()])
|
||||
? $freshModels[$model->getKey()] : null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Diff the collection with the given items.
|
||||
*
|
||||
* @param \ArrayAccess|array $items
|
||||
* @return static
|
||||
*/
|
||||
public function diff($items)
|
||||
{
|
||||
$diff = new static;
|
||||
|
||||
$dictionary = $this->getDictionary($items);
|
||||
|
||||
foreach ($this->items as $item) {
|
||||
if (! isset($dictionary[$item->getKey()])) {
|
||||
$diff->add($item);
|
||||
}
|
||||
}
|
||||
|
||||
return $diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect the collection with the given items.
|
||||
*
|
||||
* @param \ArrayAccess|array $items
|
||||
* @return static
|
||||
*/
|
||||
public function intersect($items)
|
||||
{
|
||||
$intersect = new static;
|
||||
|
||||
if (empty($items)) {
|
||||
return $intersect;
|
||||
}
|
||||
|
||||
$dictionary = $this->getDictionary($items);
|
||||
|
||||
foreach ($this->items as $item) {
|
||||
if (isset($dictionary[$item->getKey()])) {
|
||||
$intersect->add($item);
|
||||
}
|
||||
}
|
||||
|
||||
return $intersect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return only unique items from the collection.
|
||||
*
|
||||
* @param string|callable|null $key
|
||||
* @param bool $strict
|
||||
* @return static
|
||||
*/
|
||||
public function unique($key = null, $strict = false)
|
||||
{
|
||||
if (! is_null($key)) {
|
||||
return parent::unique($key, $strict);
|
||||
}
|
||||
|
||||
return new static(array_values($this->getDictionary()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns only the models from the collection with the specified keys.
|
||||
*
|
||||
* @param mixed $keys
|
||||
* @return static
|
||||
*/
|
||||
public function only($keys)
|
||||
{
|
||||
if (is_null($keys)) {
|
||||
return new static($this->items);
|
||||
}
|
||||
|
||||
$dictionary = Arr::only($this->getDictionary(), $keys);
|
||||
|
||||
return new static(array_values($dictionary));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all models in the collection except the models with specified keys.
|
||||
*
|
||||
* @param mixed $keys
|
||||
* @return static
|
||||
*/
|
||||
public function except($keys)
|
||||
{
|
||||
$dictionary = Arr::except($this->getDictionary(), $keys);
|
||||
|
||||
return new static(array_values($dictionary));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given, typically visible, attributes hidden across the entire collection.
|
||||
*
|
||||
* @param array|string $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function makeHidden($attributes)
|
||||
{
|
||||
return $this->each->makeHidden($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given, typically hidden, attributes visible across the entire collection.
|
||||
*
|
||||
* @param array|string $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function makeVisible($attributes)
|
||||
{
|
||||
return $this->each->makeVisible($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an attribute across the entire collection.
|
||||
*
|
||||
* @param array|string $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function append($attributes)
|
||||
{
|
||||
return $this->each->append($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a dictionary keyed by primary keys.
|
||||
*
|
||||
* @param \ArrayAccess|array|null $items
|
||||
* @return array
|
||||
*/
|
||||
public function getDictionary($items = null)
|
||||
{
|
||||
$items = is_null($items) ? $this->items : $items;
|
||||
|
||||
$dictionary = [];
|
||||
|
||||
foreach ($items as $value) {
|
||||
$dictionary[$value->getKey()] = $value;
|
||||
}
|
||||
|
||||
return $dictionary;
|
||||
}
|
||||
|
||||
/**
|
||||
* The following methods are intercepted to always return base collections.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get an array with the values of a given key.
|
||||
*
|
||||
* @param string|array $value
|
||||
* @param string|null $key
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function pluck($value, $key = null)
|
||||
{
|
||||
return $this->toBase()->pluck($value, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the keys of the collection items.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function keys()
|
||||
{
|
||||
return $this->toBase()->keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip the collection together with one or more arrays.
|
||||
*
|
||||
* @param mixed ...$items
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function zip($items)
|
||||
{
|
||||
return $this->toBase()->zip(...func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse the collection of items into a single array.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function collapse()
|
||||
{
|
||||
return $this->toBase()->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a flattened array of the items in the collection.
|
||||
*
|
||||
* @param int $depth
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function flatten($depth = INF)
|
||||
{
|
||||
return $this->toBase()->flatten($depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip the items in the collection.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function flip()
|
||||
{
|
||||
return $this->toBase()->flip();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pad collection to the specified length with a value.
|
||||
*
|
||||
* @param int $size
|
||||
* @param mixed $value
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function pad($size, $value)
|
||||
{
|
||||
return $this->toBase()->pad($size, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the comparison function to detect duplicates.
|
||||
*
|
||||
* @param bool $strict
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function duplicateComparator($strict)
|
||||
{
|
||||
return function ($a, $b) {
|
||||
return $a->is($b);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the entities being queued.
|
||||
*
|
||||
* @return string|null
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function getQueueableClass()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$class = get_class($this->first());
|
||||
|
||||
$this->each(function ($model) use ($class) {
|
||||
if (get_class($model) !== $class) {
|
||||
throw new LogicException('Queueing collections with multiple model types is not supported.');
|
||||
}
|
||||
});
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the identifiers for all of the entities.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getQueueableIds()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->first() instanceof QueueableEntity
|
||||
? $this->map->getQueueableId()->all()
|
||||
: $this->modelKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relationships of the entities being queued.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getQueueableRelations()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$relations = $this->map->getQueueableRelations()->all();
|
||||
|
||||
if (count($relations) === 0 || $relations === [[]]) {
|
||||
return [];
|
||||
} elseif (count($relations) === 1) {
|
||||
return reset($relations);
|
||||
} else {
|
||||
return array_intersect(...$relations);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the connection of the entities being queued.
|
||||
*
|
||||
* @return string|null
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function getQueueableConnection()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$connection = $this->first()->getConnectionName();
|
||||
|
||||
$this->each(function ($model) use ($connection) {
|
||||
if ($model->getConnectionName() !== $connection) {
|
||||
throw new LogicException('Queueing collections with multiple model connections is not supported.');
|
||||
}
|
||||
});
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Eloquent query builder from the collection.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function toQuery()
|
||||
{
|
||||
$model = $this->first();
|
||||
|
||||
if (! $model) {
|
||||
throw new LogicException('Unable to create query for empty collection.');
|
||||
}
|
||||
|
||||
$class = get_class($model);
|
||||
|
||||
if ($this->filter(function ($model) use ($class) {
|
||||
return ! $model instanceof $class;
|
||||
})->isNotEmpty()) {
|
||||
throw new LogicException('Unable to create query for collection with mixed types.');
|
||||
}
|
||||
|
||||
return $model->newModelQuery()->whereKey($this->modelKeys());
|
||||
}
|
||||
}
|
250
vendor/illuminate/database/Eloquent/Concerns/GuardsAttributes.php
vendored
Normal file
250
vendor/illuminate/database/Eloquent/Concerns/GuardsAttributes.php
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait GuardsAttributes
|
||||
{
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [];
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = ['*'];
|
||||
|
||||
/**
|
||||
* Indicates if all mass assignment is enabled.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $unguarded = false;
|
||||
|
||||
/**
|
||||
* The actual columns that exist on the database and can be guarded.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $guardableColumns = [];
|
||||
|
||||
/**
|
||||
* Get the fillable attributes for the model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFillable()
|
||||
{
|
||||
return $this->fillable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fillable attributes for the model.
|
||||
*
|
||||
* @param array $fillable
|
||||
* @return $this
|
||||
*/
|
||||
public function fillable(array $fillable)
|
||||
{
|
||||
$this->fillable = $fillable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge new fillable attributes with existing fillable attributes on the model.
|
||||
*
|
||||
* @param array $fillable
|
||||
* @return $this
|
||||
*/
|
||||
public function mergeFillable(array $fillable)
|
||||
{
|
||||
$this->fillable = array_merge($this->fillable, $fillable);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the guarded attributes for the model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getGuarded()
|
||||
{
|
||||
return $this->guarded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the guarded attributes for the model.
|
||||
*
|
||||
* @param array $guarded
|
||||
* @return $this
|
||||
*/
|
||||
public function guard(array $guarded)
|
||||
{
|
||||
$this->guarded = $guarded;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge new guarded attributes with existing guarded attributes on the model.
|
||||
*
|
||||
* @param array $guarded
|
||||
* @return $this
|
||||
*/
|
||||
public function mergeGuarded(array $guarded)
|
||||
{
|
||||
$this->guarded = array_merge($this->guarded, $guarded);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable all mass assignable restrictions.
|
||||
*
|
||||
* @param bool $state
|
||||
* @return void
|
||||
*/
|
||||
public static function unguard($state = true)
|
||||
{
|
||||
static::$unguarded = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the mass assignment restrictions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function reguard()
|
||||
{
|
||||
static::$unguarded = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if current state is "unguarded".
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isUnguarded()
|
||||
{
|
||||
return static::$unguarded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the given callable while being unguarded.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public static function unguarded(callable $callback)
|
||||
{
|
||||
if (static::$unguarded) {
|
||||
return $callback();
|
||||
}
|
||||
|
||||
static::unguard();
|
||||
|
||||
try {
|
||||
return $callback();
|
||||
} finally {
|
||||
static::reguard();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given attribute may be mass assigned.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function isFillable($key)
|
||||
{
|
||||
if (static::$unguarded) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the key is in the "fillable" array, we can of course assume that it's
|
||||
// a fillable attribute. Otherwise, we will check the guarded array when
|
||||
// we need to determine if the attribute is black-listed on the model.
|
||||
if (in_array($key, $this->getFillable())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the attribute is explicitly listed in the "guarded" array then we can
|
||||
// return false immediately. This means this attribute is definitely not
|
||||
// fillable and there is no point in going any further in this method.
|
||||
if ($this->isGuarded($key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return empty($this->getFillable()) &&
|
||||
strpos($key, '.') === false &&
|
||||
! Str::startsWith($key, '_');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given key is guarded.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function isGuarded($key)
|
||||
{
|
||||
if (empty($this->getGuarded())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->getGuarded() == ['*'] ||
|
||||
! empty(preg_grep('/^'.preg_quote($key).'$/i', $this->getGuarded())) ||
|
||||
! $this->isGuardableColumn($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given column is a valid, guardable column.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
protected function isGuardableColumn($key)
|
||||
{
|
||||
if (! isset(static::$guardableColumns[get_class($this)])) {
|
||||
static::$guardableColumns[get_class($this)] = $this->getConnection()
|
||||
->getSchemaBuilder()
|
||||
->getColumnListing($this->getTable());
|
||||
}
|
||||
|
||||
return in_array($key, static::$guardableColumns[get_class($this)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model is totally guarded.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function totallyGuarded()
|
||||
{
|
||||
return count($this->getFillable()) === 0 && $this->getGuarded() == ['*'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fillable attributes of a given array.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function fillableFromArray(array $attributes)
|
||||
{
|
||||
if (count($this->getFillable()) > 0 && ! static::$unguarded) {
|
||||
return array_intersect_key($attributes, array_flip($this->getFillable()));
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
1545
vendor/illuminate/database/Eloquent/Concerns/HasAttributes.php
vendored
Normal file
1545
vendor/illuminate/database/Eloquent/Concerns/HasAttributes.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
415
vendor/illuminate/database/Eloquent/Concerns/HasEvents.php
vendored
Normal file
415
vendor/illuminate/database/Eloquent/Concerns/HasEvents.php
vendored
Normal file
@ -0,0 +1,415 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Events\NullDispatcher;
|
||||
use Illuminate\Support\Arr;
|
||||
use InvalidArgumentException;
|
||||
|
||||
trait HasEvents
|
||||
{
|
||||
/**
|
||||
* The event map for the model.
|
||||
*
|
||||
* Allows for object-based events for native Eloquent events.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dispatchesEvents = [];
|
||||
|
||||
/**
|
||||
* User exposed observable events.
|
||||
*
|
||||
* These are extra user-defined events observers may subscribe to.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $observables = [];
|
||||
|
||||
/**
|
||||
* Register observers with the model.
|
||||
*
|
||||
* @param object|array|string $classes
|
||||
* @return void
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public static function observe($classes)
|
||||
{
|
||||
$instance = new static;
|
||||
|
||||
foreach (Arr::wrap($classes) as $class) {
|
||||
$instance->registerObserver($class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a single observer with the model.
|
||||
*
|
||||
* @param object|string $class
|
||||
* @return void
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function registerObserver($class)
|
||||
{
|
||||
$className = $this->resolveObserverClassName($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 ($this->getObservableEvents() as $event) {
|
||||
if (method_exists($class, $event)) {
|
||||
static::registerModelEvent($event, $className.'@'.$event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the observer's class name from an object or string.
|
||||
*
|
||||
* @param object|string $class
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function resolveObserverClassName($class)
|
||||
{
|
||||
if (is_object($class)) {
|
||||
return get_class($class);
|
||||
}
|
||||
|
||||
if (class_exists($class)) {
|
||||
return $class;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Unable to find observer: '.$class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the observable event names.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getObservableEvents()
|
||||
{
|
||||
return array_merge(
|
||||
[
|
||||
'retrieved', 'creating', 'created', 'updating', 'updated',
|
||||
'saving', 'saved', 'restoring', 'restored', 'replicating',
|
||||
'deleting', 'deleted', 'forceDeleted',
|
||||
],
|
||||
$this->observables
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the observable event names.
|
||||
*
|
||||
* @param array $observables
|
||||
* @return $this
|
||||
*/
|
||||
public function setObservableEvents(array $observables)
|
||||
{
|
||||
$this->observables = $observables;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an observable event name.
|
||||
*
|
||||
* @param array|mixed $observables
|
||||
* @return void
|
||||
*/
|
||||
public function addObservableEvents($observables)
|
||||
{
|
||||
$this->observables = array_unique(array_merge(
|
||||
$this->observables, is_array($observables) ? $observables : func_get_args()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an observable event name.
|
||||
*
|
||||
* @param array|mixed $observables
|
||||
* @return void
|
||||
*/
|
||||
public function removeObservableEvents($observables)
|
||||
{
|
||||
$this->observables = array_diff(
|
||||
$this->observables, is_array($observables) ? $observables : func_get_args()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = static::class;
|
||||
|
||||
static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire the given event for the model.
|
||||
*
|
||||
* @param string $event
|
||||
* @param bool $halt
|
||||
* @return mixed
|
||||
*/
|
||||
protected function fireModelEvent($event, $halt = true)
|
||||
{
|
||||
if (! isset(static::$dispatcher)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// First, we will get the proper method to call on the event dispatcher, and then we
|
||||
// will attempt to fire a custom, object based event for the given event. If that
|
||||
// returns a result we can return that result, or we'll call the string events.
|
||||
$method = $halt ? 'until' : 'dispatch';
|
||||
|
||||
$result = $this->filterModelEventResults(
|
||||
$this->fireCustomModelEvent($event, $method)
|
||||
);
|
||||
|
||||
if ($result === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! empty($result) ? $result : static::$dispatcher->{$method}(
|
||||
"eloquent.{$event}: ".static::class, $this
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire a custom model event for the given event.
|
||||
*
|
||||
* @param string $event
|
||||
* @param string $method
|
||||
* @return mixed|null
|
||||
*/
|
||||
protected function fireCustomModelEvent($event, $method)
|
||||
{
|
||||
if (! isset($this->dispatchesEvents[$event])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$result = static::$dispatcher->$method(new $this->dispatchesEvents[$event]($this));
|
||||
|
||||
if (! is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the model event results.
|
||||
*
|
||||
* @param mixed $result
|
||||
* @return mixed
|
||||
*/
|
||||
protected function filterModelEventResults($result)
|
||||
{
|
||||
if (is_array($result)) {
|
||||
$result = array_filter($result, function ($response) {
|
||||
return ! is_null($response);
|
||||
});
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a retrieved model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function retrieved($callback)
|
||||
{
|
||||
static::registerModelEvent('retrieved', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 replicating model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function replicating($callback)
|
||||
{
|
||||
static::registerModelEvent('replicating', $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}: ".static::class);
|
||||
}
|
||||
|
||||
foreach (array_values($instance->dispatchesEvents) as $event) {
|
||||
static::$dispatcher->forget($event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event dispatcher instance.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Events\Dispatcher
|
||||
*/
|
||||
public static function getEventDispatcher()
|
||||
{
|
||||
return static::$dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the event dispatcher instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Events\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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a callback without firing any model events for any model type.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public static function withoutEvents(callable $callback)
|
||||
{
|
||||
$dispatcher = static::getEventDispatcher();
|
||||
|
||||
if ($dispatcher) {
|
||||
static::setEventDispatcher(new NullDispatcher($dispatcher));
|
||||
}
|
||||
|
||||
try {
|
||||
return $callback();
|
||||
} finally {
|
||||
if ($dispatcher) {
|
||||
static::setEventDispatcher($dispatcher);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
71
vendor/illuminate/database/Eloquent/Concerns/HasGlobalScopes.php
vendored
Normal file
71
vendor/illuminate/database/Eloquent/Concerns/HasGlobalScopes.php
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Database\Eloquent\Scope;
|
||||
use Illuminate\Support\Arr;
|
||||
use InvalidArgumentException;
|
||||
|
||||
trait HasGlobalScopes
|
||||
{
|
||||
/**
|
||||
* Register a new global scope on the model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Scope|\Closure|string $scope
|
||||
* @param \Closure|null $implementation
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function addGlobalScope($scope, Closure $implementation = null)
|
||||
{
|
||||
if (is_string($scope) && ! is_null($implementation)) {
|
||||
return static::$globalScopes[static::class][$scope] = $implementation;
|
||||
} elseif ($scope instanceof Closure) {
|
||||
return static::$globalScopes[static::class][spl_object_hash($scope)] = $scope;
|
||||
} elseif ($scope instanceof Scope) {
|
||||
return static::$globalScopes[static::class][get_class($scope)] = $scope;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Global scope must be an instance of Closure or Scope.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a model has a global scope.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Scope|string $scope
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasGlobalScope($scope)
|
||||
{
|
||||
return ! is_null(static::getGlobalScope($scope));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a global scope registered with the model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Scope|string $scope
|
||||
* @return \Illuminate\Database\Eloquent\Scope|\Closure|null
|
||||
*/
|
||||
public static function getGlobalScope($scope)
|
||||
{
|
||||
if (is_string($scope)) {
|
||||
return Arr::get(static::$globalScopes, static::class.'.'.$scope);
|
||||
}
|
||||
|
||||
return Arr::get(
|
||||
static::$globalScopes, static::class.'.'.get_class($scope)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the global scopes for this class instance.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getGlobalScopes()
|
||||
{
|
||||
return Arr::get(static::$globalScopes, static::class, []);
|
||||
}
|
||||
}
|
870
vendor/illuminate/database/Eloquent/Concerns/HasRelationships.php
vendored
Normal file
870
vendor/illuminate/database/Eloquent/Concerns/HasRelationships.php
vendored
Normal file
@ -0,0 +1,870 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphOne;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait HasRelationships
|
||||
{
|
||||
/**
|
||||
* The loaded relationships for the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $relations = [];
|
||||
|
||||
/**
|
||||
* The relationships that should be touched on save.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $touches = [];
|
||||
|
||||
/**
|
||||
* The many to many relationship methods.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $manyMethods = [
|
||||
'belongsToMany', 'morphToMany', 'morphedByMany',
|
||||
];
|
||||
|
||||
/**
|
||||
* The relation resolver callbacks.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $relationResolvers = [];
|
||||
|
||||
/**
|
||||
* Define a dynamic relation resolver.
|
||||
*
|
||||
* @param string $name
|
||||
* @param \Closure $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function resolveRelationUsing($name, Closure $callback)
|
||||
{
|
||||
static::$relationResolvers = array_replace_recursive(
|
||||
static::$relationResolvers,
|
||||
[static::class => [$name => $callback]]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a one-to-one relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string|null $foreignKey
|
||||
* @param string|null $localKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function hasOne($related, $foreignKey = null, $localKey = null)
|
||||
{
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
$foreignKey = $foreignKey ?: $this->getForeignKey();
|
||||
|
||||
$localKey = $localKey ?: $this->getKeyName();
|
||||
|
||||
return $this->newHasOne($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new HasOne relationship.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $foreignKey
|
||||
* @param string $localKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
protected function newHasOne(Builder $query, Model $parent, $foreignKey, $localKey)
|
||||
{
|
||||
return new HasOne($query, $parent, $foreignKey, $localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a has-one-through relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $through
|
||||
* @param string|null $firstKey
|
||||
* @param string|null $secondKey
|
||||
* @param string|null $localKey
|
||||
* @param string|null $secondLocalKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOneThrough
|
||||
*/
|
||||
public function hasOneThrough($related, $through, $firstKey = null, $secondKey = null, $localKey = null, $secondLocalKey = null)
|
||||
{
|
||||
$through = new $through;
|
||||
|
||||
$firstKey = $firstKey ?: $this->getForeignKey();
|
||||
|
||||
$secondKey = $secondKey ?: $through->getForeignKey();
|
||||
|
||||
return $this->newHasOneThrough(
|
||||
$this->newRelatedInstance($related)->newQuery(), $this, $through,
|
||||
$firstKey, $secondKey, $localKey ?: $this->getKeyName(),
|
||||
$secondLocalKey ?: $through->getKeyName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new HasOneThrough relationship.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $farParent
|
||||
* @param \Illuminate\Database\Eloquent\Model $throughParent
|
||||
* @param string $firstKey
|
||||
* @param string $secondKey
|
||||
* @param string $localKey
|
||||
* @param string $secondLocalKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOneThrough
|
||||
*/
|
||||
protected function newHasOneThrough(Builder $query, Model $farParent, Model $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey)
|
||||
{
|
||||
return new HasOneThrough($query, $farParent, $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic one-to-one relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $name
|
||||
* @param string|null $type
|
||||
* @param string|null $id
|
||||
* @param string|null $localKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphOne
|
||||
*/
|
||||
public function morphOne($related, $name, $type = null, $id = null, $localKey = null)
|
||||
{
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
[$type, $id] = $this->getMorphs($name, $type, $id);
|
||||
|
||||
$table = $instance->getTable();
|
||||
|
||||
$localKey = $localKey ?: $this->getKeyName();
|
||||
|
||||
return $this->newMorphOne($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id, $localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new MorphOne relationship.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
* @param string $localKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphOne
|
||||
*/
|
||||
protected function newMorphOne(Builder $query, Model $parent, $type, $id, $localKey)
|
||||
{
|
||||
return new MorphOne($query, $parent, $type, $id, $localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define an inverse one-to-one or many relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string|null $foreignKey
|
||||
* @param string|null $ownerKey
|
||||
* @param string|null $relation
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function belongsTo($related, $foreignKey = null, $ownerKey = 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)) {
|
||||
$relation = $this->guessBelongsToRelation();
|
||||
}
|
||||
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
// 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 = Str::snake($relation).'_'.$instance->getKeyName();
|
||||
}
|
||||
|
||||
// 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.
|
||||
$ownerKey = $ownerKey ?: $instance->getKeyName();
|
||||
|
||||
return $this->newBelongsTo(
|
||||
$instance->newQuery(), $this, $foreignKey, $ownerKey, $relation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new BelongsTo relationship.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $child
|
||||
* @param string $foreignKey
|
||||
* @param string $ownerKey
|
||||
* @param string $relation
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
protected function newBelongsTo(Builder $query, Model $child, $foreignKey, $ownerKey, $relation)
|
||||
{
|
||||
return new BelongsTo($query, $child, $foreignKey, $ownerKey, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic, inverse one-to-one or many relationship.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @param string|null $type
|
||||
* @param string|null $id
|
||||
* @param string|null $ownerKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
public function morphTo($name = null, $type = null, $id = null, $ownerKey = 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.
|
||||
$name = $name ?: $this->guessBelongsToRelation();
|
||||
|
||||
[$type, $id] = $this->getMorphs(
|
||||
Str::snake($name), $type, $id
|
||||
);
|
||||
|
||||
// If the type value is null it is probably safe to assume we're eager loading
|
||||
// the relationship. In this case we'll just pass in a dummy query where we
|
||||
// need to remove any eager loads that may already be defined on a model.
|
||||
return is_null($class = $this->{$type}) || $class === ''
|
||||
? $this->morphEagerTo($name, $type, $id, $ownerKey)
|
||||
: $this->morphInstanceTo($class, $name, $type, $id, $ownerKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic, inverse one-to-one or many relationship.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
* @param string $ownerKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
protected function morphEagerTo($name, $type, $id, $ownerKey)
|
||||
{
|
||||
return $this->newMorphTo(
|
||||
$this->newQuery()->setEagerLoads([]), $this, $id, $ownerKey, $type, $name
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic, inverse one-to-one or many relationship.
|
||||
*
|
||||
* @param string $target
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
* @param string $ownerKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
protected function morphInstanceTo($target, $name, $type, $id, $ownerKey)
|
||||
{
|
||||
$instance = $this->newRelatedInstance(
|
||||
static::getActualClassNameForMorph($target)
|
||||
);
|
||||
|
||||
return $this->newMorphTo(
|
||||
$instance->newQuery(), $this, $id, $ownerKey ?? $instance->getKeyName(), $type, $name
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new MorphTo relationship.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $foreignKey
|
||||
* @param string $ownerKey
|
||||
* @param string $type
|
||||
* @param string $relation
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
protected function newMorphTo(Builder $query, Model $parent, $foreignKey, $ownerKey, $type, $relation)
|
||||
{
|
||||
return new MorphTo($query, $parent, $foreignKey, $ownerKey, $type, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the actual class name for a given morph class.
|
||||
*
|
||||
* @param string $class
|
||||
* @return string
|
||||
*/
|
||||
public static function getActualClassNameForMorph($class)
|
||||
{
|
||||
return Arr::get(Relation::morphMap() ?: [], $class, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess the "belongs to" relationship name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function guessBelongsToRelation()
|
||||
{
|
||||
[$one, $two, $caller] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
|
||||
|
||||
return $caller['function'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a one-to-many relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string|null $foreignKey
|
||||
* @param string|null $localKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function hasMany($related, $foreignKey = null, $localKey = null)
|
||||
{
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
$foreignKey = $foreignKey ?: $this->getForeignKey();
|
||||
|
||||
$localKey = $localKey ?: $this->getKeyName();
|
||||
|
||||
return $this->newHasMany(
|
||||
$instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new HasMany relationship.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $foreignKey
|
||||
* @param string $localKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
protected function newHasMany(Builder $query, Model $parent, $foreignKey, $localKey)
|
||||
{
|
||||
return new HasMany($query, $parent, $foreignKey, $localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a has-many-through relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $through
|
||||
* @param string|null $firstKey
|
||||
* @param string|null $secondKey
|
||||
* @param string|null $localKey
|
||||
* @param string|null $secondLocalKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
|
||||
*/
|
||||
public function hasManyThrough($related, $through, $firstKey = null, $secondKey = null, $localKey = null, $secondLocalKey = null)
|
||||
{
|
||||
$through = new $through;
|
||||
|
||||
$firstKey = $firstKey ?: $this->getForeignKey();
|
||||
|
||||
$secondKey = $secondKey ?: $through->getForeignKey();
|
||||
|
||||
return $this->newHasManyThrough(
|
||||
$this->newRelatedInstance($related)->newQuery(),
|
||||
$this,
|
||||
$through,
|
||||
$firstKey,
|
||||
$secondKey,
|
||||
$localKey ?: $this->getKeyName(),
|
||||
$secondLocalKey ?: $through->getKeyName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new HasManyThrough relationship.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $farParent
|
||||
* @param \Illuminate\Database\Eloquent\Model $throughParent
|
||||
* @param string $firstKey
|
||||
* @param string $secondKey
|
||||
* @param string $localKey
|
||||
* @param string $secondLocalKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
|
||||
*/
|
||||
protected function newHasManyThrough(Builder $query, Model $farParent, Model $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey)
|
||||
{
|
||||
return new HasManyThrough($query, $farParent, $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic one-to-many relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $name
|
||||
* @param string|null $type
|
||||
* @param string|null $id
|
||||
* @param string|null $localKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
*/
|
||||
public function morphMany($related, $name, $type = null, $id = null, $localKey = null)
|
||||
{
|
||||
$instance = $this->newRelatedInstance($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.
|
||||
[$type, $id] = $this->getMorphs($name, $type, $id);
|
||||
|
||||
$table = $instance->getTable();
|
||||
|
||||
$localKey = $localKey ?: $this->getKeyName();
|
||||
|
||||
return $this->newMorphMany($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id, $localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new MorphMany relationship.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
* @param string $localKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
*/
|
||||
protected function newMorphMany(Builder $query, Model $parent, $type, $id, $localKey)
|
||||
{
|
||||
return new MorphMany($query, $parent, $type, $id, $localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a many-to-many relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string|null $table
|
||||
* @param string|null $foreignPivotKey
|
||||
* @param string|null $relatedPivotKey
|
||||
* @param string|null $parentKey
|
||||
* @param string|null $relatedKey
|
||||
* @param string|null $relation
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function belongsToMany($related, $table = null, $foreignPivotKey = null, $relatedPivotKey = null,
|
||||
$parentKey = null, $relatedKey = 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->guessBelongsToManyRelation();
|
||||
}
|
||||
|
||||
// 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.
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
$foreignPivotKey = $foreignPivotKey ?: $this->getForeignKey();
|
||||
|
||||
$relatedPivotKey = $relatedPivotKey ?: $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, $instance);
|
||||
}
|
||||
|
||||
return $this->newBelongsToMany(
|
||||
$instance->newQuery(), $this, $table, $foreignPivotKey,
|
||||
$relatedPivotKey, $parentKey ?: $this->getKeyName(),
|
||||
$relatedKey ?: $instance->getKeyName(), $relation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new BelongsToMany relationship.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $table
|
||||
* @param string $foreignPivotKey
|
||||
* @param string $relatedPivotKey
|
||||
* @param string $parentKey
|
||||
* @param string $relatedKey
|
||||
* @param string|null $relationName
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
protected function newBelongsToMany(Builder $query, Model $parent, $table, $foreignPivotKey, $relatedPivotKey,
|
||||
$parentKey, $relatedKey, $relationName = null)
|
||||
{
|
||||
return new BelongsToMany($query, $parent, $table, $foreignPivotKey, $relatedPivotKey, $parentKey, $relatedKey, $relationName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic many-to-many relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $name
|
||||
* @param string|null $table
|
||||
* @param string|null $foreignPivotKey
|
||||
* @param string|null $relatedPivotKey
|
||||
* @param string|null $parentKey
|
||||
* @param string|null $relatedKey
|
||||
* @param bool $inverse
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
*/
|
||||
public function morphToMany($related, $name, $table = null, $foreignPivotKey = null,
|
||||
$relatedPivotKey = null, $parentKey = null,
|
||||
$relatedKey = null, $inverse = false)
|
||||
{
|
||||
$caller = $this->guessBelongsToManyRelation();
|
||||
|
||||
// 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.
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
$foreignPivotKey = $foreignPivotKey ?: $name.'_id';
|
||||
|
||||
$relatedPivotKey = $relatedPivotKey ?: $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.
|
||||
if (! $table) {
|
||||
$words = preg_split('/(_)/u', $name, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
$lastWord = array_pop($words);
|
||||
|
||||
$table = implode('', $words).Str::plural($lastWord);
|
||||
}
|
||||
|
||||
return $this->newMorphToMany(
|
||||
$instance->newQuery(), $this, $name, $table,
|
||||
$foreignPivotKey, $relatedPivotKey, $parentKey ?: $this->getKeyName(),
|
||||
$relatedKey ?: $instance->getKeyName(), $caller, $inverse
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a new MorphToMany relationship.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $name
|
||||
* @param string $table
|
||||
* @param string $foreignPivotKey
|
||||
* @param string $relatedPivotKey
|
||||
* @param string $parentKey
|
||||
* @param string $relatedKey
|
||||
* @param string|null $relationName
|
||||
* @param bool $inverse
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
*/
|
||||
protected function newMorphToMany(Builder $query, Model $parent, $name, $table, $foreignPivotKey,
|
||||
$relatedPivotKey, $parentKey, $relatedKey,
|
||||
$relationName = null, $inverse = false)
|
||||
{
|
||||
return new MorphToMany($query, $parent, $name, $table, $foreignPivotKey, $relatedPivotKey, $parentKey, $relatedKey,
|
||||
$relationName, $inverse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic, inverse many-to-many relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $name
|
||||
* @param string|null $table
|
||||
* @param string|null $foreignPivotKey
|
||||
* @param string|null $relatedPivotKey
|
||||
* @param string|null $parentKey
|
||||
* @param string|null $relatedKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
*/
|
||||
public function morphedByMany($related, $name, $table = null, $foreignPivotKey = null,
|
||||
$relatedPivotKey = null, $parentKey = null, $relatedKey = null)
|
||||
{
|
||||
$foreignPivotKey = $foreignPivotKey ?: $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.
|
||||
$relatedPivotKey = $relatedPivotKey ?: $name.'_id';
|
||||
|
||||
return $this->morphToMany(
|
||||
$related, $name, $table, $foreignPivotKey,
|
||||
$relatedPivotKey, $parentKey, $relatedKey, true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relationship name of the belongsToMany relationship.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function guessBelongsToManyRelation()
|
||||
{
|
||||
$caller = Arr::first(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), function ($trace) {
|
||||
return ! in_array(
|
||||
$trace['function'],
|
||||
array_merge(static::$manyMethods, ['guessBelongsToManyRelation'])
|
||||
);
|
||||
});
|
||||
|
||||
return ! is_null($caller) ? $caller['function'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the joining table name for a many-to-many relation.
|
||||
*
|
||||
* @param string $related
|
||||
* @param \Illuminate\Database\Eloquent\Model|null $instance
|
||||
* @return string
|
||||
*/
|
||||
public function joiningTable($related, $instance = null)
|
||||
{
|
||||
// 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.
|
||||
$segments = [
|
||||
$instance ? $instance->joiningTableSegment()
|
||||
: Str::snake(class_basename($related)),
|
||||
$this->joiningTableSegment(),
|
||||
];
|
||||
|
||||
// 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($segments);
|
||||
|
||||
return strtolower(implode('_', $segments));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this model's half of the intermediate table name for belongsToMany relationships.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function joiningTableSegment()
|
||||
{
|
||||
return Str::snake(class_basename($this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model touches a given relation.
|
||||
*
|
||||
* @param string $relation
|
||||
* @return bool
|
||||
*/
|
||||
public function touches($relation)
|
||||
{
|
||||
return in_array($relation, $this->getTouchedRelations());
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch the owning relations of the model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function touchOwners()
|
||||
{
|
||||
foreach ($this->getTouchedRelations() as $relation) {
|
||||
$this->$relation()->touch();
|
||||
|
||||
if ($this->$relation instanceof self) {
|
||||
$this->$relation->fireModelEvent('saved', false);
|
||||
|
||||
$this->$relation->touchOwners();
|
||||
} elseif ($this->$relation instanceof Collection) {
|
||||
$this->$relation->each->touchOwners();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the polymorphic relationship columns.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
* @return array
|
||||
*/
|
||||
protected function getMorphs($name, $type, $id)
|
||||
{
|
||||
return [$type ?: $name.'_type', $id ?: $name.'_id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name for polymorphic relations.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMorphClass()
|
||||
{
|
||||
$morphMap = Relation::morphMap();
|
||||
|
||||
if (! empty($morphMap) && in_array(static::class, $morphMap)) {
|
||||
return array_search(static::class, $morphMap, true);
|
||||
}
|
||||
|
||||
return static::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new model instance for a related model.
|
||||
*
|
||||
* @param string $class
|
||||
* @return mixed
|
||||
*/
|
||||
protected function newRelatedInstance($class)
|
||||
{
|
||||
return tap(new $class, function ($instance) {
|
||||
if (! $instance->getConnectionName()) {
|
||||
$instance->setConnection($this->connection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 given relationship on the model.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setRelation($relation, $value)
|
||||
{
|
||||
$this->relations[$relation] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset a loaded relationship.
|
||||
*
|
||||
* @param string $relation
|
||||
* @return $this
|
||||
*/
|
||||
public function unsetRelation($relation)
|
||||
{
|
||||
unset($this->relations[$relation]);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate the instance and unset all the loaded relations.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withoutRelations()
|
||||
{
|
||||
$model = clone $this;
|
||||
|
||||
return $model->unsetRelations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset all the loaded relations for the instance.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function unsetRelations()
|
||||
{
|
||||
$this->relations = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relationships that are touched on save.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTouchedRelations()
|
||||
{
|
||||
return $this->touches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the relationships that are touched on save.
|
||||
*
|
||||
* @param array $touches
|
||||
* @return $this
|
||||
*/
|
||||
public function setTouchedRelations(array $touches)
|
||||
{
|
||||
$this->touches = $touches;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
149
vendor/illuminate/database/Eloquent/Concerns/HasTimestamps.php
vendored
Normal file
149
vendor/illuminate/database/Eloquent/Concerns/HasTimestamps.php
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Illuminate\Support\Facades\Date;
|
||||
|
||||
trait HasTimestamps
|
||||
{
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
/**
|
||||
* Update the model's update timestamp.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function touch()
|
||||
{
|
||||
if (! $this->usesTimestamps()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->updateTimestamps();
|
||||
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the creation and update timestamps.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function updateTimestamps()
|
||||
{
|
||||
$time = $this->freshTimestamp();
|
||||
|
||||
$updatedAtColumn = $this->getUpdatedAtColumn();
|
||||
|
||||
if (! is_null($updatedAtColumn) && ! $this->isDirty($updatedAtColumn)) {
|
||||
$this->setUpdatedAt($time);
|
||||
}
|
||||
|
||||
$createdAtColumn = $this->getCreatedAtColumn();
|
||||
|
||||
if (! $this->exists && ! is_null($createdAtColumn) && ! $this->isDirty($createdAtColumn)) {
|
||||
$this->setCreatedAt($time);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the "created at" attribute.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setCreatedAt($value)
|
||||
{
|
||||
$this->{$this->getCreatedAtColumn()} = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the "updated at" attribute.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setUpdatedAt($value)
|
||||
{
|
||||
$this->{$this->getUpdatedAtColumn()} = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fresh timestamp for the model.
|
||||
*
|
||||
* @return \Illuminate\Support\Carbon
|
||||
*/
|
||||
public function freshTimestamp()
|
||||
{
|
||||
return Date::now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fresh timestamp for the model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function freshTimestampString()
|
||||
{
|
||||
return $this->fromDateTime($this->freshTimestamp());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model uses timestamps.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function usesTimestamps()
|
||||
{
|
||||
return $this->timestamps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "created at" column.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getCreatedAtColumn()
|
||||
{
|
||||
return static::CREATED_AT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "updated at" column.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getUpdatedAtColumn()
|
||||
{
|
||||
return static::UPDATED_AT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified "created at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedCreatedAtColumn()
|
||||
{
|
||||
return $this->qualifyColumn($this->getCreatedAtColumn());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified "updated at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedUpdatedAtColumn()
|
||||
{
|
||||
return $this->qualifyColumn($this->getUpdatedAtColumn());
|
||||
}
|
||||
}
|
130
vendor/illuminate/database/Eloquent/Concerns/HidesAttributes.php
vendored
Normal file
130
vendor/illuminate/database/Eloquent/Concerns/HidesAttributes.php
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Closure;
|
||||
|
||||
trait HidesAttributes
|
||||
{
|
||||
/**
|
||||
* The attributes that should be hidden for serialization.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $hidden = [];
|
||||
|
||||
/**
|
||||
* The attributes that should be visible in serialization.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $visible = [];
|
||||
|
||||
/**
|
||||
* Get the hidden attributes for the model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getHidden()
|
||||
{
|
||||
return $this->hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hidden attributes for the model.
|
||||
*
|
||||
* @param array $hidden
|
||||
* @return $this
|
||||
*/
|
||||
public function setHidden(array $hidden)
|
||||
{
|
||||
$this->hidden = $hidden;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the visible attributes for the model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getVisible()
|
||||
{
|
||||
return $this->visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the visible attributes for the model.
|
||||
*
|
||||
* @param array $visible
|
||||
* @return $this
|
||||
*/
|
||||
public function setVisible(array $visible)
|
||||
{
|
||||
$this->visible = $visible;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given, typically hidden, attributes visible.
|
||||
*
|
||||
* @param array|string|null $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function makeVisible($attributes)
|
||||
{
|
||||
$attributes = is_array($attributes) ? $attributes : func_get_args();
|
||||
|
||||
$this->hidden = array_diff($this->hidden, $attributes);
|
||||
|
||||
if (! empty($this->visible)) {
|
||||
$this->visible = array_merge($this->visible, $attributes);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given, typically hidden, attributes visible if the given truth test passes.
|
||||
*
|
||||
* @param bool|Closure $condition
|
||||
* @param array|string|null $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function makeVisibleIf($condition, $attributes)
|
||||
{
|
||||
$condition = $condition instanceof Closure ? $condition($this) : $condition;
|
||||
|
||||
return $condition ? $this->makeVisible($attributes) : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given, typically visible, attributes hidden.
|
||||
*
|
||||
* @param array|string|null $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function makeHidden($attributes)
|
||||
{
|
||||
$this->hidden = array_merge(
|
||||
$this->hidden, is_array($attributes) ? $attributes : func_get_args()
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given, typically visible, attributes hidden if the given truth test passes.
|
||||
*
|
||||
* @param bool|Closure $condition
|
||||
* @param array|string|null $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function makeHiddenIf($condition, $attributes)
|
||||
{
|
||||
$condition = $condition instanceof Closure ? $condition($this) : $condition;
|
||||
|
||||
return value($condition) ? $this->makeHidden($attributes) : $this;
|
||||
}
|
||||
}
|
498
vendor/illuminate/database/Eloquent/Concerns/QueriesRelationships.php
vendored
Normal file
498
vendor/illuminate/database/Eloquent/Concerns/QueriesRelationships.php
vendored
Normal file
@ -0,0 +1,498 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
|
||||
trait QueriesRelationships
|
||||
{
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Relations\Relation|string $relation
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @param string $boolean
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function has($relation, $operator = '>=', $count = 1, $boolean = 'and', Closure $callback = null)
|
||||
{
|
||||
if (is_string($relation)) {
|
||||
if (strpos($relation, '.') !== false) {
|
||||
return $this->hasNested($relation, $operator, $count, $boolean, $callback);
|
||||
}
|
||||
|
||||
$relation = $this->getRelationWithoutConstraints($relation);
|
||||
}
|
||||
|
||||
if ($relation instanceof MorphTo) {
|
||||
throw new RuntimeException('Please use whereHasMorph() for MorphTo relationships.');
|
||||
}
|
||||
|
||||
// If we only need to check for the existence of the relation, then we can optimize
|
||||
// the subquery to only run a "where exists" clause instead of this full "count"
|
||||
// clause. This will make these queries run much faster compared with a count.
|
||||
$method = $this->canUseExistsForExistenceCheck($operator, $count)
|
||||
? 'getRelationExistenceQuery'
|
||||
: 'getRelationExistenceCountQuery';
|
||||
|
||||
$hasQuery = $relation->{$method}(
|
||||
$relation->getRelated()->newQueryWithoutRelationships(), $this
|
||||
);
|
||||
|
||||
// Next we will call any given callback as an "anonymous" scope so they can get the
|
||||
// proper logical grouping of the where clauses if needed by this Eloquent query
|
||||
// builder. Then, we will be ready to finalize and return this query instance.
|
||||
if ($callback) {
|
||||
$hasQuery->callScope($callback);
|
||||
}
|
||||
|
||||
return $this->addHasWhere(
|
||||
$hasQuery, $relation, $operator, $count, $boolean
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add nested relationship count / exists conditions to the query.
|
||||
*
|
||||
* Sets up recursive call to whereHas until we finish the nested relation.
|
||||
*
|
||||
* @param string $relations
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @param string $boolean
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
protected function hasNested($relations, $operator = '>=', $count = 1, $boolean = 'and', $callback = null)
|
||||
{
|
||||
$relations = explode('.', $relations);
|
||||
|
||||
$doesntHave = $operator === '<' && $count === 1;
|
||||
|
||||
if ($doesntHave) {
|
||||
$operator = '>=';
|
||||
$count = 1;
|
||||
}
|
||||
|
||||
$closure = function ($q) use (&$closure, &$relations, $operator, $count, $callback) {
|
||||
// In order to nest "has", we need to add count relation constraints on the
|
||||
// callback Closure. We'll do this by simply passing the Closure its own
|
||||
// reference to itself so it calls itself recursively on each segment.
|
||||
count($relations) > 1
|
||||
? $q->whereHas(array_shift($relations), $closure)
|
||||
: $q->has(array_shift($relations), $operator, $count, 'and', $callback);
|
||||
};
|
||||
|
||||
return $this->has(array_shift($relations), $doesntHave ? '<' : '>=', 1, $boolean, $closure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query with an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function orHas($relation, $operator = '>=', $count = 1)
|
||||
{
|
||||
return $this->has($relation, $operator, $count, 'or');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param string $boolean
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function doesntHave($relation, $boolean = 'and', Closure $callback = null)
|
||||
{
|
||||
return $this->has($relation, '<', 1, $boolean, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query with an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function orDoesntHave($relation)
|
||||
{
|
||||
return $this->doesntHave($relation, 'or');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query with where clauses.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Closure|null $callback
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function whereHas($relation, Closure $callback = null, $operator = '>=', $count = 1)
|
||||
{
|
||||
return $this->has($relation, $operator, $count, 'and', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query with where clauses and an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Closure|null $callback
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function orWhereHas($relation, Closure $callback = null, $operator = '>=', $count = 1)
|
||||
{
|
||||
return $this->has($relation, $operator, $count, 'or', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query with where clauses.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function whereDoesntHave($relation, Closure $callback = null)
|
||||
{
|
||||
return $this->doesntHave($relation, 'and', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query with where clauses and an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function orWhereDoesntHave($relation, Closure $callback = null)
|
||||
{
|
||||
return $this->doesntHave($relation, 'or', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param string|array $types
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @param string $boolean
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function hasMorph($relation, $types, $operator = '>=', $count = 1, $boolean = 'and', Closure $callback = null)
|
||||
{
|
||||
$relation = $this->getRelationWithoutConstraints($relation);
|
||||
|
||||
$types = (array) $types;
|
||||
|
||||
if ($types === ['*']) {
|
||||
$types = $this->model->newModelQuery()->distinct()->pluck($relation->getMorphType())->filter()->all();
|
||||
}
|
||||
|
||||
foreach ($types as &$type) {
|
||||
$type = Relation::getMorphedModel($type) ?? $type;
|
||||
}
|
||||
|
||||
return $this->where(function ($query) use ($relation, $callback, $operator, $count, $types) {
|
||||
foreach ($types as $type) {
|
||||
$query->orWhere(function ($query) use ($relation, $callback, $operator, $count, $type) {
|
||||
$belongsTo = $this->getBelongsToRelation($relation, $type);
|
||||
|
||||
if ($callback) {
|
||||
$callback = function ($query) use ($callback, $type) {
|
||||
return $callback($query, $type);
|
||||
};
|
||||
}
|
||||
|
||||
$query->where($this->query->from.'.'.$relation->getMorphType(), '=', (new $type)->getMorphClass())
|
||||
->whereHas($belongsTo, $callback, $operator, $count);
|
||||
});
|
||||
}
|
||||
}, null, null, $boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the BelongsTo relationship for a single polymorphic type.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphTo $relation
|
||||
* @param string $type
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
protected function getBelongsToRelation(MorphTo $relation, $type)
|
||||
{
|
||||
$belongsTo = Relation::noConstraints(function () use ($relation, $type) {
|
||||
return $this->model->belongsTo(
|
||||
$type,
|
||||
$relation->getForeignKeyName(),
|
||||
$relation->getOwnerKeyName()
|
||||
);
|
||||
});
|
||||
|
||||
$belongsTo->getQuery()->mergeConstraintsFrom($relation->getQuery());
|
||||
|
||||
return $belongsTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query with an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @param string|array $types
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function orHasMorph($relation, $types, $operator = '>=', $count = 1)
|
||||
{
|
||||
return $this->hasMorph($relation, $types, $operator, $count, 'or');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param string|array $types
|
||||
* @param string $boolean
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function doesntHaveMorph($relation, $types, $boolean = 'and', Closure $callback = null)
|
||||
{
|
||||
return $this->hasMorph($relation, $types, '<', 1, $boolean, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query with an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @param string|array $types
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function orDoesntHaveMorph($relation, $types)
|
||||
{
|
||||
return $this->doesntHaveMorph($relation, $types, 'or');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query with where clauses.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param string|array $types
|
||||
* @param \Closure|null $callback
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function whereHasMorph($relation, $types, Closure $callback = null, $operator = '>=', $count = 1)
|
||||
{
|
||||
return $this->hasMorph($relation, $types, $operator, $count, 'and', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query with where clauses and an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @param string|array $types
|
||||
* @param \Closure|null $callback
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function orWhereHasMorph($relation, $types, Closure $callback = null, $operator = '>=', $count = 1)
|
||||
{
|
||||
return $this->hasMorph($relation, $types, $operator, $count, 'or', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query with where clauses.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param string|array $types
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function whereDoesntHaveMorph($relation, $types, Closure $callback = null)
|
||||
{
|
||||
return $this->doesntHaveMorph($relation, $types, 'and', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query with where clauses and an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @param string|array $types
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function orWhereDoesntHaveMorph($relation, $types, Closure $callback = null)
|
||||
{
|
||||
return $this->doesntHaveMorph($relation, $types, 'or', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subselect queries to count the relations.
|
||||
*
|
||||
* @param mixed $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function withCount($relations)
|
||||
{
|
||||
if (empty($relations)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (is_null($this->query->columns)) {
|
||||
$this->query->select([$this->query->from.'.*']);
|
||||
}
|
||||
|
||||
$relations = is_array($relations) ? $relations : func_get_args();
|
||||
|
||||
foreach ($this->parseWithRelations($relations) as $name => $constraints) {
|
||||
// First we will determine if the name has been aliased using an "as" clause on the name
|
||||
// and if it has we will extract the actual relationship name and the desired name of
|
||||
// the resulting column. This allows multiple counts on the same relationship name.
|
||||
$segments = explode(' ', $name);
|
||||
|
||||
unset($alias);
|
||||
|
||||
if (count($segments) === 3 && Str::lower($segments[1]) === 'as') {
|
||||
[$name, $alias] = [$segments[0], $segments[2]];
|
||||
}
|
||||
|
||||
$relation = $this->getRelationWithoutConstraints($name);
|
||||
|
||||
// Here we will get the relationship count query and prepare to add it to the main query
|
||||
// as a sub-select. First, we'll get the "has" query and use that to get the relation
|
||||
// count query. We will normalize the relation name then append _count as the name.
|
||||
$query = $relation->getRelationExistenceCountQuery(
|
||||
$relation->getRelated()->newQuery(), $this
|
||||
);
|
||||
|
||||
$query->callScope($constraints);
|
||||
|
||||
$query = $query->mergeConstraintsFrom($relation->getQuery())->toBase();
|
||||
|
||||
$query->orders = null;
|
||||
|
||||
$query->setBindings([], 'order');
|
||||
|
||||
if (count($query->columns) > 1) {
|
||||
$query->columns = [$query->columns[0]];
|
||||
|
||||
$query->bindings['select'] = [];
|
||||
}
|
||||
|
||||
// Finally we will add the proper result column alias to the query and run the subselect
|
||||
// statement against the query builder. Then we will return the builder instance back
|
||||
// to the developer for further constraint chaining that needs to take place on it.
|
||||
$column = $alias ?? Str::snake($name.'_count');
|
||||
|
||||
$this->selectSub($query, $column);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the "has" condition where clause to the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $hasQuery
|
||||
* @param \Illuminate\Database\Eloquent\Relations\Relation $relation
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @param string $boolean
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
protected function addHasWhere(Builder $hasQuery, Relation $relation, $operator, $count, $boolean)
|
||||
{
|
||||
$hasQuery->mergeConstraintsFrom($relation->getQuery());
|
||||
|
||||
return $this->canUseExistsForExistenceCheck($operator, $count)
|
||||
? $this->addWhereExistsQuery($hasQuery->toBase(), $boolean, $operator === '<' && $count === 1)
|
||||
: $this->addWhereCountQuery($hasQuery->toBase(), $operator, $count, $boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the where constraints from another query to the current query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $from
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function mergeConstraintsFrom(Builder $from)
|
||||
{
|
||||
$whereBindings = $from->getQuery()->getRawBindings()['where'] ?? [];
|
||||
|
||||
// Here we have some other query that we want to merge the where constraints from. We will
|
||||
// copy over any where constraints on the query as well as remove any global scopes the
|
||||
// query might have removed. Then we will return ourselves with the finished merging.
|
||||
return $this->withoutGlobalScopes(
|
||||
$from->removedScopes()
|
||||
)->mergeWheres(
|
||||
$from->getQuery()->wheres, $whereBindings
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a sub-query count clause to this query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @param string $boolean
|
||||
* @return $this
|
||||
*/
|
||||
protected function addWhereCountQuery(QueryBuilder $query, $operator = '>=', $count = 1, $boolean = 'and')
|
||||
{
|
||||
$this->query->addBinding($query->getBindings(), 'where');
|
||||
|
||||
return $this->where(
|
||||
new Expression('('.$query->toSql().')'),
|
||||
$operator,
|
||||
is_numeric($count) ? new Expression($count) : $count,
|
||||
$boolean
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "has relation" base query instance.
|
||||
*
|
||||
* @param string $relation
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
protected function getRelationWithoutConstraints($relation)
|
||||
{
|
||||
return Relation::noConstraints(function () use ($relation) {
|
||||
return $this->getModel()->{$relation}();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we can run an "exists" query to optimize performance.
|
||||
*
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @return bool
|
||||
*/
|
||||
protected function canUseExistsForExistenceCheck($operator, $count)
|
||||
{
|
||||
return ($operator === '>=' || $operator === '<') && $count === 1;
|
||||
}
|
||||
}
|
271
vendor/illuminate/database/Eloquent/Factory.php
vendored
Normal file
271
vendor/illuminate/database/Eloquent/Factory.php
vendored
Normal file
@ -0,0 +1,271 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use ArrayAccess;
|
||||
use Faker\Generator as Faker;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
class Factory implements ArrayAccess
|
||||
{
|
||||
/**
|
||||
* The model definitions in the container.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $definitions = [];
|
||||
|
||||
/**
|
||||
* The registered model states.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $states = [];
|
||||
|
||||
/**
|
||||
* The registered after making callbacks.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $afterMaking = [];
|
||||
|
||||
/**
|
||||
* The registered after creating callbacks.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $afterCreating = [];
|
||||
|
||||
/**
|
||||
* The Faker instance for the builder.
|
||||
*
|
||||
* @var \Faker\Generator
|
||||
*/
|
||||
protected $faker;
|
||||
|
||||
/**
|
||||
* Create a new factory instance.
|
||||
*
|
||||
* @param \Faker\Generator $faker
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Faker $faker)
|
||||
{
|
||||
$this->faker = $faker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new factory container.
|
||||
*
|
||||
* @param \Faker\Generator $faker
|
||||
* @param string|null $pathToFactories
|
||||
* @return static
|
||||
*/
|
||||
public static function construct(Faker $faker, $pathToFactories = null)
|
||||
{
|
||||
$pathToFactories = $pathToFactories ?: database_path('factories');
|
||||
|
||||
return (new static($faker))->load($pathToFactories);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a class with a given set of attributes.
|
||||
*
|
||||
* @param string $class
|
||||
* @param callable $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function define($class, callable $attributes)
|
||||
{
|
||||
$this->definitions[$class] = $attributes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a state with a given set of attributes.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $state
|
||||
* @param callable|array $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function state($class, $state, $attributes)
|
||||
{
|
||||
$this->states[$class][$state] = $attributes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a callback to run after making a model.
|
||||
*
|
||||
* @param string $class
|
||||
* @param callable $callback
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function afterMaking($class, callable $callback, $name = 'default')
|
||||
{
|
||||
$this->afterMaking[$class][$name][] = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a callback to run after making a model with given state.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $state
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function afterMakingState($class, $state, callable $callback)
|
||||
{
|
||||
return $this->afterMaking($class, $callback, $state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a callback to run after creating a model.
|
||||
*
|
||||
* @param string $class
|
||||
* @param callable $callback
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function afterCreating($class, callable $callback, $name = 'default')
|
||||
{
|
||||
$this->afterCreating[$class][$name][] = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a callback to run after creating a model with given state.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $state
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function afterCreatingState($class, $state, callable $callback)
|
||||
{
|
||||
return $this->afterCreating($class, $callback, $state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of the given model and persist it to the database.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*/
|
||||
public function create($class, array $attributes = [])
|
||||
{
|
||||
return $this->of($class)->create($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of the given model.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*/
|
||||
public function make($class, array $attributes = [])
|
||||
{
|
||||
return $this->of($class)->make($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw attribute array for a given model.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
public function raw($class, array $attributes = [])
|
||||
{
|
||||
return array_merge(
|
||||
call_user_func($this->definitions[$class], $this->faker), $attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder for the given model.
|
||||
*
|
||||
* @param string $class
|
||||
* @return \Illuminate\Database\Eloquent\FactoryBuilder
|
||||
*/
|
||||
public function of($class)
|
||||
{
|
||||
return new FactoryBuilder(
|
||||
$class, $this->definitions, $this->states,
|
||||
$this->afterMaking, $this->afterCreating, $this->faker
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load factories from path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function load($path)
|
||||
{
|
||||
$factory = $this;
|
||||
|
||||
if (is_dir($path)) {
|
||||
foreach (Finder::create()->files()->name('*.php')->in($path) as $file) {
|
||||
require $file->getRealPath();
|
||||
}
|
||||
}
|
||||
|
||||
return $factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given offset exists.
|
||||
*
|
||||
* @param string $offset
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->definitions[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the given offset.
|
||||
*
|
||||
* @param string $offset
|
||||
* @return mixed
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->make($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given offset to the given value.
|
||||
*
|
||||
* @param string $offset
|
||||
* @param callable $value
|
||||
* @return void
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->define($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the value at the given offset.
|
||||
*
|
||||
* @param string $offset
|
||||
* @return void
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->definitions[$offset]);
|
||||
}
|
||||
}
|
449
vendor/illuminate/database/Eloquent/FactoryBuilder.php
vendored
Normal file
449
vendor/illuminate/database/Eloquent/FactoryBuilder.php
vendored
Normal file
@ -0,0 +1,449 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use Faker\Generator as Faker;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class FactoryBuilder
|
||||
{
|
||||
use Macroable;
|
||||
|
||||
/**
|
||||
* The model definitions in the container.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $definitions;
|
||||
|
||||
/**
|
||||
* The model being built.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $class;
|
||||
|
||||
/**
|
||||
* The database connection on which the model instance should be persisted.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* The model states.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $states;
|
||||
|
||||
/**
|
||||
* The model after making callbacks.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $afterMaking = [];
|
||||
|
||||
/**
|
||||
* The model after creating callbacks.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $afterCreating = [];
|
||||
|
||||
/**
|
||||
* The states to apply.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $activeStates = [];
|
||||
|
||||
/**
|
||||
* The Faker instance for the builder.
|
||||
*
|
||||
* @var \Faker\Generator
|
||||
*/
|
||||
protected $faker;
|
||||
|
||||
/**
|
||||
* The number of models to build.
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
protected $amount = null;
|
||||
|
||||
/**
|
||||
* Create an new builder instance.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array $definitions
|
||||
* @param array $states
|
||||
* @param array $afterMaking
|
||||
* @param array $afterCreating
|
||||
* @param \Faker\Generator $faker
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($class, array $definitions, array $states,
|
||||
array $afterMaking, array $afterCreating, Faker $faker)
|
||||
{
|
||||
$this->class = $class;
|
||||
$this->faker = $faker;
|
||||
$this->states = $states;
|
||||
$this->definitions = $definitions;
|
||||
$this->afterMaking = $afterMaking;
|
||||
$this->afterCreating = $afterCreating;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of models you wish to create / make.
|
||||
*
|
||||
* @param int $amount
|
||||
* @return $this
|
||||
*/
|
||||
public function times($amount)
|
||||
{
|
||||
$this->amount = $amount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state to be applied to the model.
|
||||
*
|
||||
* @param string $state
|
||||
* @return $this
|
||||
*/
|
||||
public function state($state)
|
||||
{
|
||||
return $this->states([$state]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the states to be applied to the model.
|
||||
*
|
||||
* @param array|mixed $states
|
||||
* @return $this
|
||||
*/
|
||||
public function states($states)
|
||||
{
|
||||
$this->activeStates = is_array($states) ? $states : func_get_args();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database connection on which the model instance should be persisted.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function connection($name)
|
||||
{
|
||||
$this->connection = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a model and persist it in the database if requested.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Closure
|
||||
*/
|
||||
public function lazy(array $attributes = [])
|
||||
{
|
||||
return function () use ($attributes) {
|
||||
return $this->create($attributes);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collection of models and persist them to the database.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model|mixed
|
||||
*/
|
||||
public function create(array $attributes = [])
|
||||
{
|
||||
$results = $this->make($attributes);
|
||||
|
||||
if ($results instanceof Model) {
|
||||
$this->store(collect([$results]));
|
||||
|
||||
$this->callAfterCreating(collect([$results]));
|
||||
} else {
|
||||
$this->store($results);
|
||||
|
||||
$this->callAfterCreating($results);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collection of models and persist them to the database.
|
||||
*
|
||||
* @param iterable $records
|
||||
* @return \Illuminate\Database\Eloquent\Collection|mixed
|
||||
*/
|
||||
public function createMany(iterable $records)
|
||||
{
|
||||
return (new $this->class)->newCollection(array_map(function ($attribute) {
|
||||
return $this->create($attribute);
|
||||
}, $records));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection name on the results and store them.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $results
|
||||
* @return void
|
||||
*/
|
||||
protected function store($results)
|
||||
{
|
||||
$results->each(function ($model) {
|
||||
if (! isset($this->connection)) {
|
||||
$model->setConnection($model->newQueryWithoutScopes()->getConnection()->getName());
|
||||
}
|
||||
|
||||
$model->save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collection of models.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model|mixed
|
||||
*/
|
||||
public function make(array $attributes = [])
|
||||
{
|
||||
if ($this->amount === null) {
|
||||
return tap($this->makeInstance($attributes), function ($instance) {
|
||||
$this->callAfterMaking(collect([$instance]));
|
||||
});
|
||||
}
|
||||
|
||||
if ($this->amount < 1) {
|
||||
return (new $this->class)->newCollection();
|
||||
}
|
||||
|
||||
$instances = (new $this->class)->newCollection(array_map(function () use ($attributes) {
|
||||
return $this->makeInstance($attributes);
|
||||
}, range(1, $this->amount)));
|
||||
|
||||
$this->callAfterMaking($instances);
|
||||
|
||||
return $instances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of raw attribute arrays.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*/
|
||||
public function raw(array $attributes = [])
|
||||
{
|
||||
if ($this->amount === null) {
|
||||
return $this->getRawAttributes($attributes);
|
||||
}
|
||||
|
||||
if ($this->amount < 1) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_map(function () use ($attributes) {
|
||||
return $this->getRawAttributes($attributes);
|
||||
}, range(1, $this->amount));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a raw attributes array for the model.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function getRawAttributes(array $attributes = [])
|
||||
{
|
||||
if (! isset($this->definitions[$this->class])) {
|
||||
throw new InvalidArgumentException("Unable to locate factory for [{$this->class}].");
|
||||
}
|
||||
|
||||
$definition = call_user_func(
|
||||
$this->definitions[$this->class],
|
||||
$this->faker, $attributes
|
||||
);
|
||||
|
||||
return $this->expandAttributes(
|
||||
array_merge($this->applyStates($definition, $attributes), $attributes)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an instance of the model with the given attributes.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected function makeInstance(array $attributes = [])
|
||||
{
|
||||
return Model::unguarded(function () use ($attributes) {
|
||||
$instance = new $this->class(
|
||||
$this->getRawAttributes($attributes)
|
||||
);
|
||||
|
||||
if (isset($this->connection)) {
|
||||
$instance->setConnection($this->connection);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the active states to the model definition array.
|
||||
*
|
||||
* @param array $definition
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function applyStates(array $definition, array $attributes = [])
|
||||
{
|
||||
foreach ($this->activeStates as $state) {
|
||||
if (! isset($this->states[$this->class][$state])) {
|
||||
if ($this->stateHasAfterCallback($state)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException("Unable to locate [{$state}] state for [{$this->class}].");
|
||||
}
|
||||
|
||||
$definition = array_merge(
|
||||
$definition,
|
||||
$this->stateAttributes($state, $attributes)
|
||||
);
|
||||
}
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the state attributes.
|
||||
*
|
||||
* @param string $state
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function stateAttributes($state, array $attributes)
|
||||
{
|
||||
$stateAttributes = $this->states[$this->class][$state];
|
||||
|
||||
if (! is_callable($stateAttributes)) {
|
||||
return $stateAttributes;
|
||||
}
|
||||
|
||||
return $stateAttributes($this->faker, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand all attributes to their underlying values.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function expandAttributes(array $attributes)
|
||||
{
|
||||
foreach ($attributes as &$attribute) {
|
||||
if (is_callable($attribute) && ! is_string($attribute) && ! is_array($attribute)) {
|
||||
$attribute = $attribute($attributes);
|
||||
}
|
||||
|
||||
if ($attribute instanceof static) {
|
||||
$attribute = $attribute->create()->getKey();
|
||||
}
|
||||
|
||||
if ($attribute instanceof Model) {
|
||||
$attribute = $attribute->getKey();
|
||||
}
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run after making callbacks on a collection of models.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @return void
|
||||
*/
|
||||
public function callAfterMaking($models)
|
||||
{
|
||||
$this->callAfter($this->afterMaking, $models);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run after creating callbacks on a collection of models.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @return void
|
||||
*/
|
||||
public function callAfterCreating($models)
|
||||
{
|
||||
$this->callAfter($this->afterCreating, $models);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call after callbacks for each model and state.
|
||||
*
|
||||
* @param array $afterCallbacks
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @return void
|
||||
*/
|
||||
protected function callAfter(array $afterCallbacks, $models)
|
||||
{
|
||||
$states = array_merge(['default'], $this->activeStates);
|
||||
|
||||
$models->each(function ($model) use ($states, $afterCallbacks) {
|
||||
foreach ($states as $state) {
|
||||
$this->callAfterCallbacks($afterCallbacks, $model, $state);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Call after callbacks for each model and state.
|
||||
*
|
||||
* @param array $afterCallbacks
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $state
|
||||
* @return void
|
||||
*/
|
||||
protected function callAfterCallbacks(array $afterCallbacks, $model, $state)
|
||||
{
|
||||
if (! isset($afterCallbacks[$this->class][$state])) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($afterCallbacks[$this->class][$state] as $callback) {
|
||||
$callback($model, $this->faker);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given state has an "after" callback.
|
||||
*
|
||||
* @param string $state
|
||||
* @return bool
|
||||
*/
|
||||
protected function stateHasAfterCallback($state)
|
||||
{
|
||||
return isset($this->afterMaking[$this->class][$state]) ||
|
||||
isset($this->afterCreating[$this->class][$state]);
|
||||
}
|
||||
}
|
50
vendor/illuminate/database/Eloquent/HigherOrderBuilderProxy.php
vendored
Normal file
50
vendor/illuminate/database/Eloquent/HigherOrderBuilderProxy.php
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
/**
|
||||
* @mixin \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
class HigherOrderBuilderProxy
|
||||
{
|
||||
/**
|
||||
* The collection being operated on.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected $builder;
|
||||
|
||||
/**
|
||||
* The method being proxied.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $method;
|
||||
|
||||
/**
|
||||
* Create a new proxy instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @param string $method
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $builder, $method)
|
||||
{
|
||||
$this->method = $method;
|
||||
$this->builder = $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy a scope call onto the query builder.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
return $this->builder->{$this->method}(function ($value) use ($method, $parameters) {
|
||||
return $value->{$method}(...$parameters);
|
||||
});
|
||||
}
|
||||
}
|
49
vendor/illuminate/database/Eloquent/JsonEncodingException.php
vendored
Normal file
49
vendor/illuminate/database/Eloquent/JsonEncodingException.php
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class JsonEncodingException extends RuntimeException
|
||||
{
|
||||
/**
|
||||
* Create a new JSON encoding exception for the model.
|
||||
*
|
||||
* @param mixed $model
|
||||
* @param string $message
|
||||
* @return static
|
||||
*/
|
||||
public static function forModel($model, $message)
|
||||
{
|
||||
return new static('Error encoding model ['.get_class($model).'] with ID ['.$model->getKey().'] to JSON: '.$message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JSON encoding exception for the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Resources\Json\JsonResource $resource
|
||||
* @param string $message
|
||||
* @return static
|
||||
*/
|
||||
public static function forResource($resource, $message)
|
||||
{
|
||||
$model = $resource->resource;
|
||||
|
||||
return new static('Error encoding resource ['.get_class($resource).'] with model ['.get_class($model).'] with ID ['.$model->getKey().'] to JSON: '.$message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JSON encoding exception for an attribute.
|
||||
*
|
||||
* @param mixed $model
|
||||
* @param mixed $key
|
||||
* @param string $message
|
||||
* @return static
|
||||
*/
|
||||
public static function forAttribute($model, $key, $message)
|
||||
{
|
||||
$class = get_class($model);
|
||||
|
||||
return new static("Unable to encode attribute [{$key}] for model [{$class}] to JSON: {$message}.");
|
||||
}
|
||||
}
|
10
vendor/illuminate/database/Eloquent/MassAssignmentException.php
vendored
Executable file
10
vendor/illuminate/database/Eloquent/MassAssignmentException.php
vendored
Executable file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class MassAssignmentException extends RuntimeException
|
||||
{
|
||||
//
|
||||
}
|
1784
vendor/illuminate/database/Eloquent/Model.php
vendored
Normal file
1784
vendor/illuminate/database/Eloquent/Model.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
66
vendor/illuminate/database/Eloquent/ModelNotFoundException.php
vendored
Executable file
66
vendor/illuminate/database/Eloquent/ModelNotFoundException.php
vendored
Executable file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use RuntimeException;
|
||||
|
||||
class ModelNotFoundException extends RuntimeException
|
||||
{
|
||||
/**
|
||||
* Name of the affected Eloquent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* The affected model IDs.
|
||||
*
|
||||
* @var int|array
|
||||
*/
|
||||
protected $ids;
|
||||
|
||||
/**
|
||||
* Set the affected Eloquent model and instance ids.
|
||||
*
|
||||
* @param string $model
|
||||
* @param int|array $ids
|
||||
* @return $this
|
||||
*/
|
||||
public function setModel($model, $ids = [])
|
||||
{
|
||||
$this->model = $model;
|
||||
$this->ids = Arr::wrap($ids);
|
||||
|
||||
$this->message = "No query results for model [{$model}]";
|
||||
|
||||
if (count($this->ids) > 0) {
|
||||
$this->message .= ' '.implode(', ', $this->ids);
|
||||
} else {
|
||||
$this->message .= '.';
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the affected Eloquent model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getModel()
|
||||
{
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the affected Eloquent model IDs.
|
||||
*
|
||||
* @return int|array
|
||||
*/
|
||||
public function getIds()
|
||||
{
|
||||
return $this->ids;
|
||||
}
|
||||
}
|
29
vendor/illuminate/database/Eloquent/QueueEntityResolver.php
vendored
Normal file
29
vendor/illuminate/database/Eloquent/QueueEntityResolver.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use Illuminate\Contracts\Queue\EntityNotFoundException;
|
||||
use Illuminate\Contracts\Queue\EntityResolver as EntityResolverContract;
|
||||
|
||||
class QueueEntityResolver implements EntityResolverContract
|
||||
{
|
||||
/**
|
||||
* Resolve the entity for the given ID.
|
||||
*
|
||||
* @param string $type
|
||||
* @param mixed $id
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Queue\EntityNotFoundException
|
||||
*/
|
||||
public function resolve($type, $id)
|
||||
{
|
||||
$instance = (new $type)->find($id);
|
||||
|
||||
if ($instance) {
|
||||
return $instance;
|
||||
}
|
||||
|
||||
throw new EntityNotFoundException($type, $id);
|
||||
}
|
||||
}
|
41
vendor/illuminate/database/Eloquent/RelationNotFoundException.php
vendored
Executable file
41
vendor/illuminate/database/Eloquent/RelationNotFoundException.php
vendored
Executable file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class RelationNotFoundException extends RuntimeException
|
||||
{
|
||||
/**
|
||||
* The name of the affected Eloquent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $model;
|
||||
|
||||
/**
|
||||
* The name of the relation.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $relation;
|
||||
|
||||
/**
|
||||
* Create a new exception instance.
|
||||
*
|
||||
* @param object $model
|
||||
* @param string $relation
|
||||
* @return static
|
||||
*/
|
||||
public static function make($model, $relation)
|
||||
{
|
||||
$class = get_class($model);
|
||||
|
||||
$instance = new static("Call to undefined relationship [{$relation}] on model [{$class}].");
|
||||
|
||||
$instance->model = $class;
|
||||
$instance->relation = $relation;
|
||||
|
||||
return $instance;
|
||||
}
|
||||
}
|
361
vendor/illuminate/database/Eloquent/Relations/BelongsTo.php
vendored
Executable file
361
vendor/illuminate/database/Eloquent/Relations/BelongsTo.php
vendored
Executable file
@ -0,0 +1,361 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
|
||||
|
||||
class BelongsTo extends Relation
|
||||
{
|
||||
use SupportsDefaultModels;
|
||||
|
||||
/**
|
||||
* The child model instance of the relation.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected $child;
|
||||
|
||||
/**
|
||||
* The foreign key of the parent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $foreignKey;
|
||||
|
||||
/**
|
||||
* The associated key on the parent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $ownerKey;
|
||||
|
||||
/**
|
||||
* The name of the relationship.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $relationName;
|
||||
|
||||
/**
|
||||
* The count of self joins.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected static $selfJoinCount = 0;
|
||||
|
||||
/**
|
||||
* Create a new belongs to relationship instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $child
|
||||
* @param string $foreignKey
|
||||
* @param string $ownerKey
|
||||
* @param string $relationName
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $child, $foreignKey, $ownerKey, $relationName)
|
||||
{
|
||||
$this->ownerKey = $ownerKey;
|
||||
$this->relationName = $relationName;
|
||||
$this->foreignKey = $foreignKey;
|
||||
|
||||
// In the underlying base relationship class, this variable is referred to as
|
||||
// the "parent" since most relationships are not inversed. But, since this
|
||||
// one is we will create a "child" variable for much better readability.
|
||||
$this->child = $child;
|
||||
|
||||
parent::__construct($query, $child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
if (is_null($this->child->{$this->foreignKey})) {
|
||||
return $this->getDefaultFor($this->parent);
|
||||
}
|
||||
|
||||
return $this->query->first() ?: $this->getDefaultFor($this->parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base constraints on the relation query.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addConstraints()
|
||||
{
|
||||
if (static::$constraints) {
|
||||
// For belongs to relationships, which are essentially the inverse of has one
|
||||
// or has many relationships, we need to actually query on the primary key
|
||||
// of the related models matching on the foreign key that's on a parent.
|
||||
$table = $this->related->getTable();
|
||||
|
||||
$this->query->where($table.'.'.$this->ownerKey, '=', $this->child->{$this->foreignKey});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
public function addEagerConstraints(array $models)
|
||||
{
|
||||
// We'll grab the primary key name of the related models since it could be set to
|
||||
// a non-standard name and not "id". We will then construct the constraint for
|
||||
// our eagerly loading query so it returns the proper models from execution.
|
||||
$key = $this->related->getTable().'.'.$this->ownerKey;
|
||||
|
||||
$whereIn = $this->whereInMethod($this->related, $this->ownerKey);
|
||||
|
||||
$this->query->{$whereIn}($key, $this->getEagerModelKeys($models));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather the keys from an array of related models.
|
||||
*
|
||||
* @param array $models
|
||||
* @return array
|
||||
*/
|
||||
protected function getEagerModelKeys(array $models)
|
||||
{
|
||||
$keys = [];
|
||||
|
||||
// First we need to gather all of the keys from the parent models so we know what
|
||||
// to query for via the eager loading query. We will add them to an array then
|
||||
// execute a "where in" statement to gather up all of those related records.
|
||||
foreach ($models as $model) {
|
||||
if (! is_null($value = $model->{$this->foreignKey})) {
|
||||
$keys[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
sort($keys);
|
||||
|
||||
return array_values(array_unique($keys));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->getDefaultFor($model));
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
$foreign = $this->foreignKey;
|
||||
|
||||
$owner = $this->ownerKey;
|
||||
|
||||
// First we will get to build a dictionary of the child models by their primary
|
||||
// key of the relationship, then we can easily match the children back onto
|
||||
// the parents using that dictionary and the primary key of the children.
|
||||
$dictionary = [];
|
||||
|
||||
foreach ($results as $result) {
|
||||
$dictionary[$result->getAttribute($owner)] = $result;
|
||||
}
|
||||
|
||||
// Once we have the dictionary constructed, we can loop through all the parents
|
||||
// and match back onto their children using these keys of the dictionary and
|
||||
// the primary key of the children to map them onto the correct instances.
|
||||
foreach ($models as $model) {
|
||||
if (isset($dictionary[$model->{$foreign}])) {
|
||||
$model->setRelation($relation, $dictionary[$model->{$foreign}]);
|
||||
}
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate the model instance to the given parent.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model|int|string $model
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function associate($model)
|
||||
{
|
||||
$ownerKey = $model instanceof Model ? $model->getAttribute($this->ownerKey) : $model;
|
||||
|
||||
$this->child->setAttribute($this->foreignKey, $ownerKey);
|
||||
|
||||
if ($model instanceof Model) {
|
||||
$this->child->setRelation($this->relationName, $model);
|
||||
} else {
|
||||
$this->child->unsetRelation($this->relationName);
|
||||
}
|
||||
|
||||
return $this->child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dissociate previously associated model from the given parent.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function dissociate()
|
||||
{
|
||||
$this->child->setAttribute($this->foreignKey, null);
|
||||
|
||||
return $this->child->setRelation($this->relationName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
if ($parentQuery->getQuery()->from == $query->getQuery()->from) {
|
||||
return $this->getRelationExistenceQueryForSelfRelation($query, $parentQuery, $columns);
|
||||
}
|
||||
|
||||
return $query->select($columns)->whereColumn(
|
||||
$this->getQualifiedForeignKeyName(), '=', $query->qualifyColumn($this->ownerKey)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship query on the same table.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQueryForSelfRelation(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
$query->select($columns)->from(
|
||||
$query->getModel()->getTable().' as '.$hash = $this->getRelationCountHash()
|
||||
);
|
||||
|
||||
$query->getModel()->setTable($hash);
|
||||
|
||||
return $query->whereColumn(
|
||||
$hash.'.'.$this->ownerKey, '=', $this->getQualifiedForeignKeyName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a relationship join table hash.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRelationCountHash()
|
||||
{
|
||||
return 'laravel_reserved_'.static::$selfJoinCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the related model has an auto-incrementing ID.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function relationHasIncrementingId()
|
||||
{
|
||||
return $this->related->getIncrementing() &&
|
||||
in_array($this->related->getKeyType(), ['int', 'integer']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new related instance for the given model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected function newRelatedInstanceFor(Model $parent)
|
||||
{
|
||||
return $this->related->newInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the child of the relationship.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function getChild()
|
||||
{
|
||||
return $this->child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key of the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getForeignKeyName()
|
||||
{
|
||||
return $this->foreignKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified foreign key of the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedForeignKeyName()
|
||||
{
|
||||
return $this->child->qualifyColumn($this->foreignKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated key of the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOwnerKeyName()
|
||||
{
|
||||
return $this->ownerKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified associated key of the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedOwnerKeyName()
|
||||
{
|
||||
return $this->related->qualifyColumn($this->ownerKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRelationName()
|
||||
{
|
||||
return $this->relationName;
|
||||
}
|
||||
}
|
1324
vendor/illuminate/database/Eloquent/Relations/BelongsToMany.php
vendored
Executable file
1324
vendor/illuminate/database/Eloquent/Relations/BelongsToMany.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
321
vendor/illuminate/database/Eloquent/Relations/Concerns/AsPivot.php
vendored
Normal file
321
vendor/illuminate/database/Eloquent/Relations/Concerns/AsPivot.php
vendored
Normal file
@ -0,0 +1,321 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations\Concerns;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait AsPivot
|
||||
{
|
||||
/**
|
||||
* The parent model of the relationship.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public $pivotParent;
|
||||
|
||||
/**
|
||||
* The name of the foreign key column.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $foreignKey;
|
||||
|
||||
/**
|
||||
* The name of the "other key" column.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $relatedKey;
|
||||
|
||||
/**
|
||||
* Create a new pivot model instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param array $attributes
|
||||
* @param string $table
|
||||
* @param bool $exists
|
||||
* @return static
|
||||
*/
|
||||
public static function fromAttributes(Model $parent, $attributes, $table, $exists = false)
|
||||
{
|
||||
$instance = new static;
|
||||
|
||||
$instance->timestamps = $instance->hasTimestampAttributes($attributes);
|
||||
|
||||
// The pivot model is a "dynamic" model since we will set the tables dynamically
|
||||
// for the instance. This allows it work for any intermediate tables for the
|
||||
// many to many relationship that are defined by this developer's classes.
|
||||
$instance->setConnection($parent->getConnectionName())
|
||||
->setTable($table)
|
||||
->forceFill($attributes)
|
||||
->syncOriginal();
|
||||
|
||||
// We store off the parent instance so we will access the timestamp column names
|
||||
// for the model, since the pivot model timestamps aren't easily configurable
|
||||
// from the developer's point of view. We can use the parents to get these.
|
||||
$instance->pivotParent = $parent;
|
||||
|
||||
$instance->exists = $exists;
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new pivot model from raw values returned from a query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param array $attributes
|
||||
* @param string $table
|
||||
* @param bool $exists
|
||||
* @return static
|
||||
*/
|
||||
public static function fromRawAttributes(Model $parent, $attributes, $table, $exists = false)
|
||||
{
|
||||
$instance = static::fromAttributes($parent, [], $table, $exists);
|
||||
|
||||
$instance->timestamps = $instance->hasTimestampAttributes($attributes);
|
||||
|
||||
$instance->setRawAttributes($attributes, $exists);
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the keys for a save update query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function setKeysForSaveQuery(Builder $query)
|
||||
{
|
||||
if (isset($this->attributes[$this->getKeyName()])) {
|
||||
return parent::setKeysForSaveQuery($query);
|
||||
}
|
||||
|
||||
$query->where($this->foreignKey, $this->getOriginal(
|
||||
$this->foreignKey, $this->getAttribute($this->foreignKey)
|
||||
));
|
||||
|
||||
return $query->where($this->relatedKey, $this->getOriginal(
|
||||
$this->relatedKey, $this->getAttribute($this->relatedKey)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the pivot model record from the database.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
if (isset($this->attributes[$this->getKeyName()])) {
|
||||
return (int) parent::delete();
|
||||
}
|
||||
|
||||
if ($this->fireModelEvent('deleting') === false) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$this->touchOwners();
|
||||
|
||||
return tap($this->getDeleteQuery()->delete(), function () {
|
||||
$this->exists = false;
|
||||
|
||||
$this->fireModelEvent('deleted', false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query builder for a delete operation on the pivot.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function getDeleteQuery()
|
||||
{
|
||||
return $this->newQueryWithoutRelationships()->where([
|
||||
$this->foreignKey => $this->getOriginal($this->foreignKey, $this->getAttribute($this->foreignKey)),
|
||||
$this->relatedKey => $this->getOriginal($this->relatedKey, $this->getAttribute($this->relatedKey)),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table associated with the model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTable()
|
||||
{
|
||||
if (! isset($this->table)) {
|
||||
$this->setTable(str_replace(
|
||||
'\\', '', Str::snake(Str::singular(class_basename($this)))
|
||||
));
|
||||
}
|
||||
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key column name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getForeignKey()
|
||||
{
|
||||
return $this->foreignKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "related key" column name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRelatedKey()
|
||||
{
|
||||
return $this->relatedKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "related key" column name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOtherKey()
|
||||
{
|
||||
return $this->getRelatedKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the key names for the pivot model instance.
|
||||
*
|
||||
* @param string $foreignKey
|
||||
* @param string $relatedKey
|
||||
* @return $this
|
||||
*/
|
||||
public function setPivotKeys($foreignKey, $relatedKey)
|
||||
{
|
||||
$this->foreignKey = $foreignKey;
|
||||
|
||||
$this->relatedKey = $relatedKey;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the pivot model or given attributes has timestamp attributes.
|
||||
*
|
||||
* @param array|null $attributes
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTimestampAttributes($attributes = null)
|
||||
{
|
||||
return array_key_exists($this->getCreatedAtColumn(), $attributes ?? $this->attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "created at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCreatedAtColumn()
|
||||
{
|
||||
return $this->pivotParent
|
||||
? $this->pivotParent->getCreatedAtColumn()
|
||||
: parent::getCreatedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "updated at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUpdatedAtColumn()
|
||||
{
|
||||
return $this->pivotParent
|
||||
? $this->pivotParent->getUpdatedAtColumn()
|
||||
: parent::getUpdatedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the queueable identity for the entity.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getQueueableId()
|
||||
{
|
||||
if (isset($this->attributes[$this->getKeyName()])) {
|
||||
return $this->getKey();
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'%s:%s:%s:%s',
|
||||
$this->foreignKey, $this->getAttribute($this->foreignKey),
|
||||
$this->relatedKey, $this->getAttribute($this->relatedKey)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new query to restore one or more models by their queueable IDs.
|
||||
*
|
||||
* @param int[]|string[]|string $ids
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function newQueryForRestoration($ids)
|
||||
{
|
||||
if (is_array($ids)) {
|
||||
return $this->newQueryForCollectionRestoration($ids);
|
||||
}
|
||||
|
||||
if (! Str::contains($ids, ':')) {
|
||||
return parent::newQueryForRestoration($ids);
|
||||
}
|
||||
|
||||
$segments = explode(':', $ids);
|
||||
|
||||
return $this->newQueryWithoutScopes()
|
||||
->where($segments[0], $segments[1])
|
||||
->where($segments[2], $segments[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new query to restore multiple models by their queueable IDs.
|
||||
*
|
||||
* @param int[]|string[] $ids
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function newQueryForCollectionRestoration(array $ids)
|
||||
{
|
||||
$ids = array_values($ids);
|
||||
|
||||
if (! Str::contains($ids[0], ':')) {
|
||||
return parent::newQueryForRestoration($ids);
|
||||
}
|
||||
|
||||
$query = $this->newQueryWithoutScopes();
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$segments = explode(':', $id);
|
||||
|
||||
$query->orWhere(function ($query) use ($segments) {
|
||||
return $query->where($segments[0], $segments[1])
|
||||
->where($segments[2], $segments[3]);
|
||||
});
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset all the loaded relations for the instance.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function unsetRelations()
|
||||
{
|
||||
$this->pivotParent = null;
|
||||
$this->relations = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
670
vendor/illuminate/database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php
vendored
Normal file
670
vendor/illuminate/database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php
vendored
Normal file
@ -0,0 +1,670 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations\Concerns;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\Pivot;
|
||||
use Illuminate\Support\Collection as BaseCollection;
|
||||
|
||||
trait InteractsWithPivotTable
|
||||
{
|
||||
/**
|
||||
* Toggles a model (or models) from the parent.
|
||||
*
|
||||
* Each existing model is detached, and non existing ones are attached.
|
||||
*
|
||||
* @param mixed $ids
|
||||
* @param bool $touch
|
||||
* @return array
|
||||
*/
|
||||
public function toggle($ids, $touch = true)
|
||||
{
|
||||
$changes = [
|
||||
'attached' => [], 'detached' => [],
|
||||
];
|
||||
|
||||
$records = $this->formatRecordsList($this->parseIds($ids));
|
||||
|
||||
// Next, we will determine which IDs should get removed from the join table by
|
||||
// checking which of the given ID/records is in the list of current records
|
||||
// and removing all of those rows from this "intermediate" joining table.
|
||||
$detach = array_values(array_intersect(
|
||||
$this->newPivotQuery()->pluck($this->relatedPivotKey)->all(),
|
||||
array_keys($records)
|
||||
));
|
||||
|
||||
if (count($detach) > 0) {
|
||||
$this->detach($detach, false);
|
||||
|
||||
$changes['detached'] = $this->castKeys($detach);
|
||||
}
|
||||
|
||||
// Finally, for all of the records which were not "detached", we'll attach the
|
||||
// records into the intermediate table. Then, we will add those attaches to
|
||||
// this change list and get ready to return these results to the callers.
|
||||
$attach = array_diff_key($records, array_flip($detach));
|
||||
|
||||
if (count($attach) > 0) {
|
||||
$this->attach($attach, [], false);
|
||||
|
||||
$changes['attached'] = array_keys($attach);
|
||||
}
|
||||
|
||||
// Once we have finished attaching or detaching the records, we will see if we
|
||||
// have done any attaching or detaching, and if we have we will touch these
|
||||
// relationships if they are configured to touch on any database updates.
|
||||
if ($touch && (count($changes['attached']) ||
|
||||
count($changes['detached']))) {
|
||||
$this->touchIfTouching();
|
||||
}
|
||||
|
||||
return $changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync the intermediate tables with a list of IDs without detaching.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model|array $ids
|
||||
* @return array
|
||||
*/
|
||||
public function syncWithoutDetaching($ids)
|
||||
{
|
||||
return $this->sync($ids, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync the intermediate tables with a list of IDs or collection of models.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model|array $ids
|
||||
* @param bool $detaching
|
||||
* @return array
|
||||
*/
|
||||
public function sync($ids, $detaching = true)
|
||||
{
|
||||
$changes = [
|
||||
'attached' => [], 'detached' => [], 'updated' => [],
|
||||
];
|
||||
|
||||
// First we need to attach any of the associated models that are not currently
|
||||
// in this joining table. We'll spin through the given IDs, checking to see
|
||||
// if they exist in the array of current ones, and if not we will insert.
|
||||
$current = $this->getCurrentlyAttachedPivots()
|
||||
->pluck($this->relatedPivotKey)->all();
|
||||
|
||||
$detach = array_diff($current, array_keys(
|
||||
$records = $this->formatRecordsList($this->parseIds($ids))
|
||||
));
|
||||
|
||||
// Next, we will take the differences of the currents and given IDs and detach
|
||||
// all of the entities that exist in the "current" array but are not in the
|
||||
// array of the new IDs given to the method which will complete the sync.
|
||||
if ($detaching && count($detach) > 0) {
|
||||
$this->detach($detach);
|
||||
|
||||
$changes['detached'] = $this->castKeys($detach);
|
||||
}
|
||||
|
||||
// Now we are finally ready to attach the new records. Note that we'll disable
|
||||
// touching until after the entire operation is complete so we don't fire a
|
||||
// ton of touch operations until we are totally done syncing the records.
|
||||
$changes = array_merge(
|
||||
$changes, $this->attachNew($records, $current, false)
|
||||
);
|
||||
|
||||
// Once we have finished attaching or detaching the records, we will see if we
|
||||
// have done any attaching or detaching, and if we have we will touch these
|
||||
// relationships if they are configured to touch on any database updates.
|
||||
if (count($changes['attached']) ||
|
||||
count($changes['updated'])) {
|
||||
$this->touchIfTouching();
|
||||
}
|
||||
|
||||
return $changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the sync / toggle record list so that it is keyed by ID.
|
||||
*
|
||||
* @param array $records
|
||||
* @return array
|
||||
*/
|
||||
protected function formatRecordsList(array $records)
|
||||
{
|
||||
return collect($records)->mapWithKeys(function ($attributes, $id) {
|
||||
if (! is_array($attributes)) {
|
||||
[$id, $attributes] = [$attributes, []];
|
||||
}
|
||||
|
||||
return [$id => $attributes];
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach all of the records that aren't in the given current records.
|
||||
*
|
||||
* @param array $records
|
||||
* @param array $current
|
||||
* @param bool $touch
|
||||
* @return array
|
||||
*/
|
||||
protected function attachNew(array $records, array $current, $touch = true)
|
||||
{
|
||||
$changes = ['attached' => [], 'updated' => []];
|
||||
|
||||
foreach ($records as $id => $attributes) {
|
||||
// If the ID is not in the list of existing pivot IDs, we will insert a new pivot
|
||||
// record, otherwise, we will just update this existing record on this joining
|
||||
// table, so that the developers will easily update these records pain free.
|
||||
if (! in_array($id, $current)) {
|
||||
$this->attach($id, $attributes, $touch);
|
||||
|
||||
$changes['attached'][] = $this->castKey($id);
|
||||
}
|
||||
|
||||
// Now we'll try to update an existing pivot record with the attributes that were
|
||||
// given to the method. If the model is actually updated we will add it to the
|
||||
// list of updated pivot records so we return them back out to the consumer.
|
||||
elseif (count($attributes) > 0 &&
|
||||
$this->updateExistingPivot($id, $attributes, $touch)) {
|
||||
$changes['updated'][] = $this->castKey($id);
|
||||
}
|
||||
}
|
||||
|
||||
return $changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing pivot record on the table.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $attributes
|
||||
* @param bool $touch
|
||||
* @return int
|
||||
*/
|
||||
public function updateExistingPivot($id, array $attributes, $touch = true)
|
||||
{
|
||||
if ($this->using &&
|
||||
empty($this->pivotWheres) &&
|
||||
empty($this->pivotWhereIns) &&
|
||||
empty($this->pivotWhereNulls)) {
|
||||
return $this->updateExistingPivotUsingCustomClass($id, $attributes, $touch);
|
||||
}
|
||||
|
||||
if (in_array($this->updatedAt(), $this->pivotColumns)) {
|
||||
$attributes = $this->addTimestampsToAttachment($attributes, true);
|
||||
}
|
||||
|
||||
$updated = $this->newPivotStatementForId($this->parseId($id))->update(
|
||||
$this->castAttributes($attributes)
|
||||
);
|
||||
|
||||
if ($touch) {
|
||||
$this->touchIfTouching();
|
||||
}
|
||||
|
||||
return $updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing pivot record on the table via a custom class.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $attributes
|
||||
* @param bool $touch
|
||||
* @return int
|
||||
*/
|
||||
protected function updateExistingPivotUsingCustomClass($id, array $attributes, $touch)
|
||||
{
|
||||
$pivot = $this->getCurrentlyAttachedPivots()
|
||||
->where($this->foreignPivotKey, $this->parent->{$this->parentKey})
|
||||
->where($this->relatedPivotKey, $this->parseId($id))
|
||||
->first();
|
||||
|
||||
$updated = $pivot ? $pivot->fill($attributes)->isDirty() : false;
|
||||
|
||||
if ($updated) {
|
||||
$pivot->save();
|
||||
}
|
||||
|
||||
if ($touch) {
|
||||
$this->touchIfTouching();
|
||||
}
|
||||
|
||||
return (int) $updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a model to the parent.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $attributes
|
||||
* @param bool $touch
|
||||
* @return void
|
||||
*/
|
||||
public function attach($id, array $attributes = [], $touch = true)
|
||||
{
|
||||
if ($this->using) {
|
||||
$this->attachUsingCustomClass($id, $attributes);
|
||||
} else {
|
||||
// Here we will insert the attachment records into the pivot table. Once we have
|
||||
// inserted the records, we will touch the relationships if necessary and the
|
||||
// function will return. We can parse the IDs before inserting the records.
|
||||
$this->newPivotStatement()->insert($this->formatAttachRecords(
|
||||
$this->parseIds($id), $attributes
|
||||
));
|
||||
}
|
||||
|
||||
if ($touch) {
|
||||
$this->touchIfTouching();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a model to the parent using a custom class.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $attributes
|
||||
* @return void
|
||||
*/
|
||||
protected function attachUsingCustomClass($id, array $attributes)
|
||||
{
|
||||
$records = $this->formatAttachRecords(
|
||||
$this->parseIds($id), $attributes
|
||||
);
|
||||
|
||||
foreach ($records as $record) {
|
||||
$this->newPivot($record, false)->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of records to insert into the pivot table.
|
||||
*
|
||||
* @param array $ids
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function formatAttachRecords($ids, array $attributes)
|
||||
{
|
||||
$records = [];
|
||||
|
||||
$hasTimestamps = ($this->hasPivotColumn($this->createdAt()) ||
|
||||
$this->hasPivotColumn($this->updatedAt()));
|
||||
|
||||
// To create the attachment records, we will simply spin through the IDs given
|
||||
// and create a new record to insert for each ID. Each ID may actually be a
|
||||
// key in the array, with extra attributes to be placed in other columns.
|
||||
foreach ($ids as $key => $value) {
|
||||
$records[] = $this->formatAttachRecord(
|
||||
$key, $value, $attributes, $hasTimestamps
|
||||
);
|
||||
}
|
||||
|
||||
return $records;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a full attachment record payload.
|
||||
*
|
||||
* @param int $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @param bool $hasTimestamps
|
||||
* @return array
|
||||
*/
|
||||
protected function formatAttachRecord($key, $value, $attributes, $hasTimestamps)
|
||||
{
|
||||
[$id, $attributes] = $this->extractAttachIdAndAttributes($key, $value, $attributes);
|
||||
|
||||
return array_merge(
|
||||
$this->baseAttachRecord($id, $hasTimestamps), $this->castAttributes($attributes)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attach record ID and extra attributes.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function extractAttachIdAndAttributes($key, $value, array $attributes)
|
||||
{
|
||||
return is_array($value)
|
||||
? [$key, array_merge($value, $attributes)]
|
||||
: [$value, $attributes];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new pivot attachment record.
|
||||
*
|
||||
* @param int $id
|
||||
* @param bool $timed
|
||||
* @return array
|
||||
*/
|
||||
protected function baseAttachRecord($id, $timed)
|
||||
{
|
||||
$record[$this->relatedPivotKey] = $id;
|
||||
|
||||
$record[$this->foreignPivotKey] = $this->parent->{$this->parentKey};
|
||||
|
||||
// If the record needs to have creation and update timestamps, we will make
|
||||
// them by calling the parent model's "freshTimestamp" method which will
|
||||
// provide us with a fresh timestamp in this model's preferred format.
|
||||
if ($timed) {
|
||||
$record = $this->addTimestampsToAttachment($record);
|
||||
}
|
||||
|
||||
foreach ($this->pivotValues as $value) {
|
||||
$record[$value['column']] = $value['value'];
|
||||
}
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the creation and update timestamps on an attach record.
|
||||
*
|
||||
* @param array $record
|
||||
* @param bool $exists
|
||||
* @return array
|
||||
*/
|
||||
protected function addTimestampsToAttachment(array $record, $exists = false)
|
||||
{
|
||||
$fresh = $this->parent->freshTimestamp();
|
||||
|
||||
if ($this->using) {
|
||||
$pivotModel = new $this->using;
|
||||
|
||||
$fresh = $fresh->format($pivotModel->getDateFormat());
|
||||
}
|
||||
|
||||
if (! $exists && $this->hasPivotColumn($this->createdAt())) {
|
||||
$record[$this->createdAt()] = $fresh;
|
||||
}
|
||||
|
||||
if ($this->hasPivotColumn($this->updatedAt())) {
|
||||
$record[$this->updatedAt()] = $fresh;
|
||||
}
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given column is defined as a pivot column.
|
||||
*
|
||||
* @param string $column
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPivotColumn($column)
|
||||
{
|
||||
return in_array($column, $this->pivotColumns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach models from the relationship.
|
||||
*
|
||||
* @param mixed $ids
|
||||
* @param bool $touch
|
||||
* @return int
|
||||
*/
|
||||
public function detach($ids = null, $touch = true)
|
||||
{
|
||||
if ($this->using &&
|
||||
! empty($ids) &&
|
||||
empty($this->pivotWheres) &&
|
||||
empty($this->pivotWhereIns) &&
|
||||
empty($this->pivotWhereNulls)) {
|
||||
$results = $this->detachUsingCustomClass($ids);
|
||||
} else {
|
||||
$query = $this->newPivotQuery();
|
||||
|
||||
// If associated IDs were passed to the method we will only delete those
|
||||
// associations, otherwise all of the association ties will be broken.
|
||||
// We'll return the numbers of affected rows when we do the deletes.
|
||||
if (! is_null($ids)) {
|
||||
$ids = $this->parseIds($ids);
|
||||
|
||||
if (empty($ids)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$query->whereIn($this->relatedPivotKey, (array) $ids);
|
||||
}
|
||||
|
||||
// Once we have all of the conditions set on the statement, we are ready
|
||||
// to run the delete on the pivot table. Then, if the touch parameter
|
||||
// is true, we will go ahead and touch all related models to sync.
|
||||
$results = $query->delete();
|
||||
}
|
||||
|
||||
if ($touch) {
|
||||
$this->touchIfTouching();
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach models from the relationship using a custom class.
|
||||
*
|
||||
* @param mixed $ids
|
||||
* @return int
|
||||
*/
|
||||
protected function detachUsingCustomClass($ids)
|
||||
{
|
||||
$results = 0;
|
||||
|
||||
foreach ($this->parseIds($ids) as $id) {
|
||||
$results += $this->newPivot([
|
||||
$this->foreignPivotKey => $this->parent->{$this->parentKey},
|
||||
$this->relatedPivotKey => $id,
|
||||
], true)->delete();
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pivot models that are currently attached.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function getCurrentlyAttachedPivots()
|
||||
{
|
||||
return $this->newPivotQuery()->get()->map(function ($record) {
|
||||
$class = $this->using ? $this->using : Pivot::class;
|
||||
|
||||
$pivot = $class::fromRawAttributes($this->parent, (array) $record, $this->getTable(), true);
|
||||
|
||||
return $pivot->setPivotKeys($this->foreignPivotKey, $this->relatedPivotKey);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new pivot model instance.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param bool $exists
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Pivot
|
||||
*/
|
||||
public function newPivot(array $attributes = [], $exists = false)
|
||||
{
|
||||
$pivot = $this->related->newPivot(
|
||||
$this->parent, $attributes, $this->table, $exists, $this->using
|
||||
);
|
||||
|
||||
return $pivot->setPivotKeys($this->foreignPivotKey, $this->relatedPivotKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new existing pivot model instance.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Pivot
|
||||
*/
|
||||
public function newExistingPivot(array $attributes = [])
|
||||
{
|
||||
return $this->newPivot($attributes, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new plain query builder for the pivot table.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function newPivotStatement()
|
||||
{
|
||||
return $this->query->getQuery()->newQuery()->from($this->table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new pivot statement for a given "other" ID.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function newPivotStatementForId($id)
|
||||
{
|
||||
return $this->newPivotQuery()->whereIn($this->relatedPivotKey, $this->parseIds($id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new query builder for the pivot table.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function newPivotQuery()
|
||||
{
|
||||
$query = $this->newPivotStatement();
|
||||
|
||||
foreach ($this->pivotWheres as $arguments) {
|
||||
$query->where(...$arguments);
|
||||
}
|
||||
|
||||
foreach ($this->pivotWhereIns as $arguments) {
|
||||
$query->whereIn(...$arguments);
|
||||
}
|
||||
|
||||
foreach ($this->pivotWhereNulls as $arguments) {
|
||||
$query->whereNull(...$arguments);
|
||||
}
|
||||
|
||||
return $query->where($this->foreignPivotKey, $this->parent->{$this->parentKey});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the columns on the pivot table to retrieve.
|
||||
*
|
||||
* @param array|mixed $columns
|
||||
* @return $this
|
||||
*/
|
||||
public function withPivot($columns)
|
||||
{
|
||||
$this->pivotColumns = array_merge(
|
||||
$this->pivotColumns, is_array($columns) ? $columns : func_get_args()
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the IDs from the given mixed value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
protected function parseIds($value)
|
||||
{
|
||||
if ($value instanceof Model) {
|
||||
return [$value->{$this->relatedKey}];
|
||||
}
|
||||
|
||||
if ($value instanceof Collection) {
|
||||
return $value->pluck($this->relatedKey)->all();
|
||||
}
|
||||
|
||||
if ($value instanceof BaseCollection) {
|
||||
return $value->toArray();
|
||||
}
|
||||
|
||||
return (array) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID from the given mixed value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function parseId($value)
|
||||
{
|
||||
return $value instanceof Model ? $value->{$this->relatedKey} : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast the given keys to integers if they are numeric and string otherwise.
|
||||
*
|
||||
* @param array $keys
|
||||
* @return array
|
||||
*/
|
||||
protected function castKeys(array $keys)
|
||||
{
|
||||
return array_map(function ($v) {
|
||||
return $this->castKey($v);
|
||||
}, $keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast the given key to convert to primary key type.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @return mixed
|
||||
*/
|
||||
protected function castKey($key)
|
||||
{
|
||||
return $this->getTypeSwapValue(
|
||||
$this->related->getKeyType(),
|
||||
$key
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast the given pivot attributes.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function castAttributes($attributes)
|
||||
{
|
||||
return $this->using
|
||||
? $this->newPivot()->fill($attributes)->getAttributes()
|
||||
: $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a given value to a given type value.
|
||||
*
|
||||
* @param string $type
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getTypeSwapValue($type, $value)
|
||||
{
|
||||
switch (strtolower($type)) {
|
||||
case 'int':
|
||||
case 'integer':
|
||||
return (int) $value;
|
||||
case 'real':
|
||||
case 'float':
|
||||
case 'double':
|
||||
return (float) $value;
|
||||
case 'string':
|
||||
return (string) $value;
|
||||
default:
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
}
|
63
vendor/illuminate/database/Eloquent/Relations/Concerns/SupportsDefaultModels.php
vendored
Normal file
63
vendor/illuminate/database/Eloquent/Relations/Concerns/SupportsDefaultModels.php
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations\Concerns;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
trait SupportsDefaultModels
|
||||
{
|
||||
/**
|
||||
* Indicates if a default model instance should be used.
|
||||
*
|
||||
* Alternatively, may be a Closure or array.
|
||||
*
|
||||
* @var \Closure|array|bool
|
||||
*/
|
||||
protected $withDefault;
|
||||
|
||||
/**
|
||||
* Make a new related instance for the given model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
abstract protected function newRelatedInstanceFor(Model $parent);
|
||||
|
||||
/**
|
||||
* Return a new model instance in case the relationship does not exist.
|
||||
*
|
||||
* @param \Closure|array|bool $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function withDefault($callback = true)
|
||||
{
|
||||
$this->withDefault = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default value for this relation.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return \Illuminate\Database\Eloquent\Model|null
|
||||
*/
|
||||
protected function getDefaultFor(Model $parent)
|
||||
{
|
||||
if (! $this->withDefault) {
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = $this->newRelatedInstanceFor($parent);
|
||||
|
||||
if (is_callable($this->withDefault)) {
|
||||
return call_user_func($this->withDefault, $instance, $parent) ?: $instance;
|
||||
}
|
||||
|
||||
if (is_array($this->withDefault)) {
|
||||
$instance->forceFill($this->withDefault);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
}
|
49
vendor/illuminate/database/Eloquent/Relations/HasMany.php
vendored
Executable file
49
vendor/illuminate/database/Eloquent/Relations/HasMany.php
vendored
Executable file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class HasMany extends HasOneOrMany
|
||||
{
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return ! is_null($this->getParentKey())
|
||||
? $this->query->get()
|
||||
: $this->related->newCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->related->newCollection());
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $this->matchMany($models, $results, $relation);
|
||||
}
|
||||
}
|
688
vendor/illuminate/database/Eloquent/Relations/HasManyThrough.php
vendored
Normal file
688
vendor/illuminate/database/Eloquent/Relations/HasManyThrough.php
vendored
Normal file
@ -0,0 +1,688 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class HasManyThrough extends Relation
|
||||
{
|
||||
/**
|
||||
* The "through" parent model instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected $throughParent;
|
||||
|
||||
/**
|
||||
* The far parent model instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected $farParent;
|
||||
|
||||
/**
|
||||
* The near key on the relationship.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $firstKey;
|
||||
|
||||
/**
|
||||
* The far key on the relationship.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $secondKey;
|
||||
|
||||
/**
|
||||
* The local key on the relationship.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $localKey;
|
||||
|
||||
/**
|
||||
* The local key on the intermediary model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $secondLocalKey;
|
||||
|
||||
/**
|
||||
* The count of self joins.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected static $selfJoinCount = 0;
|
||||
|
||||
/**
|
||||
* Create a new has many through relationship instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $farParent
|
||||
* @param \Illuminate\Database\Eloquent\Model $throughParent
|
||||
* @param string $firstKey
|
||||
* @param string $secondKey
|
||||
* @param string $localKey
|
||||
* @param string $secondLocalKey
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $farParent, Model $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey)
|
||||
{
|
||||
$this->localKey = $localKey;
|
||||
$this->firstKey = $firstKey;
|
||||
$this->secondKey = $secondKey;
|
||||
$this->farParent = $farParent;
|
||||
$this->throughParent = $throughParent;
|
||||
$this->secondLocalKey = $secondLocalKey;
|
||||
|
||||
parent::__construct($query, $throughParent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base constraints on the relation query.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addConstraints()
|
||||
{
|
||||
$localValue = $this->farParent[$this->localKey];
|
||||
|
||||
$this->performJoin();
|
||||
|
||||
if (static::$constraints) {
|
||||
$this->query->where($this->getQualifiedFirstKeyName(), '=', $localValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the join clause on the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder|null $query
|
||||
* @return void
|
||||
*/
|
||||
protected function performJoin(Builder $query = null)
|
||||
{
|
||||
$query = $query ?: $this->query;
|
||||
|
||||
$farKey = $this->getQualifiedFarKeyName();
|
||||
|
||||
$query->join($this->throughParent->getTable(), $this->getQualifiedParentKeyName(), '=', $farKey);
|
||||
|
||||
if ($this->throughParentSoftDeletes()) {
|
||||
$query->withGlobalScope('SoftDeletableHasManyThrough', function ($query) {
|
||||
$query->whereNull($this->throughParent->getQualifiedDeletedAtColumn());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified parent key name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedParentKeyName()
|
||||
{
|
||||
return $this->parent->qualifyColumn($this->secondLocalKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether "through" parent of the relation uses Soft Deletes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function throughParentSoftDeletes()
|
||||
{
|
||||
return in_array(SoftDeletes::class, class_uses_recursive($this->throughParent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that trashed "through" parents should be included in the query.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withTrashedParents()
|
||||
{
|
||||
$this->query->withoutGlobalScope('SoftDeletableHasManyThrough');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
public function addEagerConstraints(array $models)
|
||||
{
|
||||
$whereIn = $this->whereInMethod($this->farParent, $this->localKey);
|
||||
|
||||
$this->query->{$whereIn}(
|
||||
$this->getQualifiedFirstKeyName(), $this->getKeys($models, $this->localKey)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->related->newCollection());
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
$dictionary = $this->buildDictionary($results);
|
||||
|
||||
// Once we have the dictionary we can simply spin through the parent models to
|
||||
// link them up with their children using the keyed dictionary to make the
|
||||
// matching very convenient and easy work. Then we'll just return them.
|
||||
foreach ($models as $model) {
|
||||
if (isset($dictionary[$key = $model->getAttribute($this->localKey)])) {
|
||||
$model->setRelation(
|
||||
$relation, $this->related->newCollection($dictionary[$key])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build model dictionary keyed by the relation's foreign key.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @return array
|
||||
*/
|
||||
protected function buildDictionary(Collection $results)
|
||||
{
|
||||
$dictionary = [];
|
||||
|
||||
// First we will create a dictionary of models keyed by the foreign key of the
|
||||
// relationship as this will allow us to quickly access all of the related
|
||||
// models without having to do nested looping which will be quite slow.
|
||||
foreach ($results as $result) {
|
||||
$dictionary[$result->laravel_through_key][] = $result;
|
||||
}
|
||||
|
||||
return $dictionary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first related model record matching the attributes or instantiate it.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function firstOrNew(array $attributes)
|
||||
{
|
||||
if (is_null($instance = $this->where($attributes)->first())) {
|
||||
$instance = $this->related->newInstance($attributes);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or update a related record matching the attributes, and fill it with values.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $values
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function updateOrCreate(array $attributes, array $values = [])
|
||||
{
|
||||
$instance = $this->firstOrNew($attributes);
|
||||
|
||||
$instance->fill($values)->save();
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a basic where clause to the query, and return the first result.
|
||||
*
|
||||
* @param \Closure|string|array $column
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @param string $boolean
|
||||
* @return \Illuminate\Database\Eloquent\Model|static
|
||||
*/
|
||||
public function firstWhere($column, $operator = null, $value = null, $boolean = 'and')
|
||||
{
|
||||
return $this->where($column, $operator, $value, $boolean)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and get the first related model.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return mixed
|
||||
*/
|
||||
public function first($columns = ['*'])
|
||||
{
|
||||
$results = $this->take(1)->get($columns);
|
||||
|
||||
return count($results) > 0 ? $results->first() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and get the first result or throw an exception.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Model|static
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function firstOrFail($columns = ['*'])
|
||||
{
|
||||
if (! is_null($model = $this->first($columns))) {
|
||||
return $model;
|
||||
}
|
||||
|
||||
throw (new ModelNotFoundException)->setModel(get_class($this->related));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a related model by its primary key.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection|null
|
||||
*/
|
||||
public function find($id, $columns = ['*'])
|
||||
{
|
||||
if (is_array($id) || $id instanceof Arrayable) {
|
||||
return $this->findMany($id, $columns);
|
||||
}
|
||||
|
||||
return $this->where(
|
||||
$this->getRelated()->getQualifiedKeyName(), '=', $id
|
||||
)->first($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find multiple related models by their primary keys.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Support\Arrayable|array $ids
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function findMany($ids, $columns = ['*'])
|
||||
{
|
||||
$ids = $ids instanceof Arrayable ? $ids->toArray() : $ids;
|
||||
|
||||
if (empty($ids)) {
|
||||
return $this->getRelated()->newCollection();
|
||||
}
|
||||
|
||||
return $this->whereIn(
|
||||
$this->getRelated()->getQualifiedKeyName(), $ids
|
||||
)->get($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a related model by its primary key or throw an exception.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function findOrFail($id, $columns = ['*'])
|
||||
{
|
||||
$result = $this->find($id, $columns);
|
||||
|
||||
$id = $id instanceof Arrayable ? $id->toArray() : $id;
|
||||
|
||||
if (is_array($id)) {
|
||||
if (count($result) === count(array_unique($id))) {
|
||||
return $result;
|
||||
}
|
||||
} elseif (! is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
throw (new ModelNotFoundException)->setModel(get_class($this->related), $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return ! is_null($this->farParent->{$this->localKey})
|
||||
? $this->get()
|
||||
: $this->related->newCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as a "select" statement.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function get($columns = ['*'])
|
||||
{
|
||||
$builder = $this->prepareQueryBuilder($columns);
|
||||
|
||||
$models = $builder->getModels();
|
||||
|
||||
// If we actually found models we will also eager load any relationships that
|
||||
// have been specified as needing to be eager loaded. This will solve the
|
||||
// n + 1 query problem for the developer and also increase performance.
|
||||
if (count($models) > 0) {
|
||||
$models = $builder->eagerLoadRelations($models);
|
||||
}
|
||||
|
||||
return $this->related->newCollection($models);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a paginator for the "select" statement.
|
||||
*
|
||||
* @param int|null $perPage
|
||||
* @param array $columns
|
||||
* @param string $pageName
|
||||
* @param int $page
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
|
||||
{
|
||||
$this->query->addSelect($this->shouldSelect($columns));
|
||||
|
||||
return $this->query->paginate($perPage, $columns, $pageName, $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paginate the given query into a simple paginator.
|
||||
*
|
||||
* @param int|null $perPage
|
||||
* @param array $columns
|
||||
* @param string $pageName
|
||||
* @param int|null $page
|
||||
* @return \Illuminate\Contracts\Pagination\Paginator
|
||||
*/
|
||||
public function simplePaginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
|
||||
{
|
||||
$this->query->addSelect($this->shouldSelect($columns));
|
||||
|
||||
return $this->query->simplePaginate($perPage, $columns, $pageName, $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the select clause for the relation query.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return array
|
||||
*/
|
||||
protected function shouldSelect(array $columns = ['*'])
|
||||
{
|
||||
if ($columns == ['*']) {
|
||||
$columns = [$this->related->getTable().'.*'];
|
||||
}
|
||||
|
||||
return array_merge($columns, [$this->getQualifiedFirstKeyName().' as laravel_through_key']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Chunk the results of the query.
|
||||
*
|
||||
* @param int $count
|
||||
* @param callable $callback
|
||||
* @return bool
|
||||
*/
|
||||
public function chunk($count, callable $callback)
|
||||
{
|
||||
return $this->prepareQueryBuilder()->chunk($count, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Chunk the results of a query by comparing numeric IDs.
|
||||
*
|
||||
* @param int $count
|
||||
* @param callable $callback
|
||||
* @param string|null $column
|
||||
* @param string|null $alias
|
||||
* @return bool
|
||||
*/
|
||||
public function chunkById($count, callable $callback, $column = null, $alias = null)
|
||||
{
|
||||
$column = $column ?? $this->getRelated()->getQualifiedKeyName();
|
||||
|
||||
$alias = $alias ?? $this->getRelated()->getKeyName();
|
||||
|
||||
return $this->prepareQueryBuilder()->chunkById($count, $callback, $column, $alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a generator for the given query.
|
||||
*
|
||||
* @return \Generator
|
||||
*/
|
||||
public function cursor()
|
||||
{
|
||||
return $this->prepareQueryBuilder()->cursor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a callback over each item while chunking.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param int $count
|
||||
* @return bool
|
||||
*/
|
||||
public function each(callable $callback, $count = 1000)
|
||||
{
|
||||
return $this->chunk($count, function ($results) use ($callback) {
|
||||
foreach ($results as $key => $value) {
|
||||
if ($callback($value, $key) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the query builder for query execution.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function prepareQueryBuilder($columns = ['*'])
|
||||
{
|
||||
$builder = $this->query->applyScopes();
|
||||
|
||||
return $builder->addSelect(
|
||||
$this->shouldSelect($builder->getQuery()->columns ? [] : $columns)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
if ($parentQuery->getQuery()->from === $query->getQuery()->from) {
|
||||
return $this->getRelationExistenceQueryForSelfRelation($query, $parentQuery, $columns);
|
||||
}
|
||||
|
||||
if ($parentQuery->getQuery()->from === $this->throughParent->getTable()) {
|
||||
return $this->getRelationExistenceQueryForThroughSelfRelation($query, $parentQuery, $columns);
|
||||
}
|
||||
|
||||
$this->performJoin($query);
|
||||
|
||||
return $query->select($columns)->whereColumn(
|
||||
$this->getQualifiedLocalKeyName(), '=', $this->getQualifiedFirstKeyName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship query on the same table.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQueryForSelfRelation(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
$query->from($query->getModel()->getTable().' as '.$hash = $this->getRelationCountHash());
|
||||
|
||||
$query->join($this->throughParent->getTable(), $this->getQualifiedParentKeyName(), '=', $hash.'.'.$this->secondKey);
|
||||
|
||||
if ($this->throughParentSoftDeletes()) {
|
||||
$query->whereNull($this->throughParent->getQualifiedDeletedAtColumn());
|
||||
}
|
||||
|
||||
$query->getModel()->setTable($hash);
|
||||
|
||||
return $query->select($columns)->whereColumn(
|
||||
$parentQuery->getQuery()->from.'.'.$this->localKey, '=', $this->getQualifiedFirstKeyName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship query on the same table as the through parent.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQueryForThroughSelfRelation(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
$table = $this->throughParent->getTable().' as '.$hash = $this->getRelationCountHash();
|
||||
|
||||
$query->join($table, $hash.'.'.$this->secondLocalKey, '=', $this->getQualifiedFarKeyName());
|
||||
|
||||
if ($this->throughParentSoftDeletes()) {
|
||||
$query->whereNull($hash.'.'.$this->throughParent->getDeletedAtColumn());
|
||||
}
|
||||
|
||||
return $query->select($columns)->whereColumn(
|
||||
$parentQuery->getQuery()->from.'.'.$this->localKey, '=', $hash.'.'.$this->firstKey
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a relationship join table hash.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRelationCountHash()
|
||||
{
|
||||
return 'laravel_reserved_'.static::$selfJoinCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the qualified foreign key on the related model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedFarKeyName()
|
||||
{
|
||||
return $this->getQualifiedForeignKeyName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key on the "through" model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFirstKeyName()
|
||||
{
|
||||
return $this->firstKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the qualified foreign key on the "through" model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedFirstKeyName()
|
||||
{
|
||||
return $this->throughParent->qualifyColumn($this->firstKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key on the related model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getForeignKeyName()
|
||||
{
|
||||
return $this->secondKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the qualified foreign key on the related model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedForeignKeyName()
|
||||
{
|
||||
return $this->related->qualifyColumn($this->secondKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the local key on the far parent model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalKeyName()
|
||||
{
|
||||
return $this->localKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the qualified local key on the far parent model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedLocalKeyName()
|
||||
{
|
||||
return $this->farParent->qualifyColumn($this->localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the local key on the intermediary model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSecondLocalKeyName()
|
||||
{
|
||||
return $this->secondLocalKey;
|
||||
}
|
||||
}
|
68
vendor/illuminate/database/Eloquent/Relations/HasOne.php
vendored
Executable file
68
vendor/illuminate/database/Eloquent/Relations/HasOne.php
vendored
Executable file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
|
||||
|
||||
class HasOne extends HasOneOrMany
|
||||
{
|
||||
use SupportsDefaultModels;
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
if (is_null($this->getParentKey())) {
|
||||
return $this->getDefaultFor($this->parent);
|
||||
}
|
||||
|
||||
return $this->query->first() ?: $this->getDefaultFor($this->parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->getDefaultFor($model));
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $this->matchOne($models, $results, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new related instance for the given model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function newRelatedInstanceFor(Model $parent)
|
||||
{
|
||||
return $this->related->newInstance()->setAttribute(
|
||||
$this->getForeignKeyName(), $parent->{$this->localKey}
|
||||
);
|
||||
}
|
||||
}
|
437
vendor/illuminate/database/Eloquent/Relations/HasOneOrMany.php
vendored
Executable file
437
vendor/illuminate/database/Eloquent/Relations/HasOneOrMany.php
vendored
Executable file
@ -0,0 +1,437 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
abstract class HasOneOrMany extends Relation
|
||||
{
|
||||
/**
|
||||
* The foreign key of the parent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $foreignKey;
|
||||
|
||||
/**
|
||||
* The local key of the parent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $localKey;
|
||||
|
||||
/**
|
||||
* The count of self joins.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected static $selfJoinCount = 0;
|
||||
|
||||
/**
|
||||
* Create a new has one or many relationship instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $foreignKey
|
||||
* @param string $localKey
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $parent, $foreignKey, $localKey)
|
||||
{
|
||||
$this->localKey = $localKey;
|
||||
$this->foreignKey = $foreignKey;
|
||||
|
||||
parent::__construct($query, $parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return an un-saved instance of the related model.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function make(array $attributes = [])
|
||||
{
|
||||
return tap($this->related->newInstance($attributes), function ($instance) {
|
||||
$this->setForeignAttributesForCreate($instance);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return an un-saved instances of the related models.
|
||||
*
|
||||
* @param iterable $records
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function makeMany($records)
|
||||
{
|
||||
$instances = $this->related->newCollection();
|
||||
|
||||
foreach ($records as $record) {
|
||||
$instances->push($this->make($record));
|
||||
}
|
||||
|
||||
return $instances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base constraints on the relation query.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addConstraints()
|
||||
{
|
||||
if (static::$constraints) {
|
||||
$this->query->where($this->foreignKey, '=', $this->getParentKey());
|
||||
|
||||
$this->query->whereNotNull($this->foreignKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
public function addEagerConstraints(array $models)
|
||||
{
|
||||
$whereIn = $this->whereInMethod($this->parent, $this->localKey);
|
||||
|
||||
$this->query->{$whereIn}(
|
||||
$this->foreignKey, $this->getKeys($models, $this->localKey)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their single parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function matchOne(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $this->matchOneOrMany($models, $results, $relation, 'one');
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their many parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function matchMany(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $this->matchOneOrMany($models, $results, $relation, 'many');
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their many parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
protected function matchOneOrMany(array $models, Collection $results, $relation, $type)
|
||||
{
|
||||
$dictionary = $this->buildDictionary($results);
|
||||
|
||||
// Once we have the dictionary we can simply spin through the parent models to
|
||||
// link them up with their children using the keyed dictionary to make the
|
||||
// matching very convenient and easy work. Then we'll just return them.
|
||||
foreach ($models as $model) {
|
||||
if (isset($dictionary[$key = $model->getAttribute($this->localKey)])) {
|
||||
$model->setRelation(
|
||||
$relation, $this->getRelationValue($dictionary, $key, $type)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a relationship by one or many type.
|
||||
*
|
||||
* @param array $dictionary
|
||||
* @param string $key
|
||||
* @param string $type
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getRelationValue(array $dictionary, $key, $type)
|
||||
{
|
||||
$value = $dictionary[$key];
|
||||
|
||||
return $type === 'one' ? reset($value) : $this->related->newCollection($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build model dictionary keyed by the relation's foreign key.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @return array
|
||||
*/
|
||||
protected function buildDictionary(Collection $results)
|
||||
{
|
||||
$foreign = $this->getForeignKeyName();
|
||||
|
||||
return $results->mapToDictionary(function ($result) use ($foreign) {
|
||||
return [$result->{$foreign} => $result];
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a model by its primary key or return new instance of the related model.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function findOrNew($id, $columns = ['*'])
|
||||
{
|
||||
if (is_null($instance = $this->find($id, $columns))) {
|
||||
$instance = $this->related->newInstance();
|
||||
|
||||
$this->setForeignAttributesForCreate($instance);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first related model record matching the attributes or instantiate it.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $values
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function firstOrNew(array $attributes, array $values = [])
|
||||
{
|
||||
if (is_null($instance = $this->where($attributes)->first())) {
|
||||
$instance = $this->related->newInstance($attributes + $values);
|
||||
|
||||
$this->setForeignAttributesForCreate($instance);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first related record matching the attributes or create it.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $values
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function firstOrCreate(array $attributes, array $values = [])
|
||||
{
|
||||
if (is_null($instance = $this->where($attributes)->first())) {
|
||||
$instance = $this->create($attributes + $values);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or update a related record matching the attributes, and fill it with values.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $values
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function updateOrCreate(array $attributes, array $values = [])
|
||||
{
|
||||
return tap($this->firstOrNew($attributes), function ($instance) use ($values) {
|
||||
$instance->fill($values);
|
||||
|
||||
$instance->save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a model instance to the parent model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return \Illuminate\Database\Eloquent\Model|false
|
||||
*/
|
||||
public function save(Model $model)
|
||||
{
|
||||
$this->setForeignAttributesForCreate($model);
|
||||
|
||||
return $model->save() ? $model : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a collection of models to the parent instance.
|
||||
*
|
||||
* @param iterable $models
|
||||
* @return iterable
|
||||
*/
|
||||
public function saveMany($models)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$this->save($model);
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the related model.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function create(array $attributes = [])
|
||||
{
|
||||
return tap($this->related->newInstance($attributes), function ($instance) {
|
||||
$this->setForeignAttributesForCreate($instance);
|
||||
|
||||
$instance->save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Collection of new instances of the related model.
|
||||
*
|
||||
* @param iterable $records
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function createMany(iterable $records)
|
||||
{
|
||||
$instances = $this->related->newCollection();
|
||||
|
||||
foreach ($records as $record) {
|
||||
$instances->push($this->create($record));
|
||||
}
|
||||
|
||||
return $instances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the foreign ID for creating a related model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return void
|
||||
*/
|
||||
protected function setForeignAttributesForCreate(Model $model)
|
||||
{
|
||||
$model->setAttribute($this->getForeignKeyName(), $this->getParentKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
if ($query->getQuery()->from == $parentQuery->getQuery()->from) {
|
||||
return $this->getRelationExistenceQueryForSelfRelation($query, $parentQuery, $columns);
|
||||
}
|
||||
|
||||
return parent::getRelationExistenceQuery($query, $parentQuery, $columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship query on the same table.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQueryForSelfRelation(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
$query->from($query->getModel()->getTable().' as '.$hash = $this->getRelationCountHash());
|
||||
|
||||
$query->getModel()->setTable($hash);
|
||||
|
||||
return $query->select($columns)->whereColumn(
|
||||
$this->getQualifiedParentKeyName(), '=', $hash.'.'.$this->getForeignKeyName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a relationship join table hash.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRelationCountHash()
|
||||
{
|
||||
return 'laravel_reserved_'.static::$selfJoinCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key for comparing against the parent key in "has" query.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getExistenceCompareKey()
|
||||
{
|
||||
return $this->getQualifiedForeignKeyName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key value of the parent's local key.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getParentKey()
|
||||
{
|
||||
return $this->parent->getAttribute($this->localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified parent key name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedParentKeyName()
|
||||
{
|
||||
return $this->parent->qualifyColumn($this->localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plain foreign key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getForeignKeyName()
|
||||
{
|
||||
$segments = explode('.', $this->getQualifiedForeignKeyName());
|
||||
|
||||
return end($segments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key for the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedForeignKeyName()
|
||||
{
|
||||
return $this->foreignKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the local key for the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalKeyName()
|
||||
{
|
||||
return $this->localKey;
|
||||
}
|
||||
}
|
76
vendor/illuminate/database/Eloquent/Relations/HasOneThrough.php
vendored
Normal file
76
vendor/illuminate/database/Eloquent/Relations/HasOneThrough.php
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
|
||||
|
||||
class HasOneThrough extends HasManyThrough
|
||||
{
|
||||
use SupportsDefaultModels;
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return $this->first() ?: $this->getDefaultFor($this->farParent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->getDefaultFor($model));
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
$dictionary = $this->buildDictionary($results);
|
||||
|
||||
// Once we have the dictionary we can simply spin through the parent models to
|
||||
// link them up with their children using the keyed dictionary to make the
|
||||
// matching very convenient and easy work. Then we'll just return them.
|
||||
foreach ($models as $model) {
|
||||
if (isset($dictionary[$key = $model->getAttribute($this->localKey)])) {
|
||||
$value = $dictionary[$key];
|
||||
$model->setRelation(
|
||||
$relation, reset($value)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new related instance for the given model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function newRelatedInstanceFor(Model $parent)
|
||||
{
|
||||
return $this->related->newInstance();
|
||||
}
|
||||
}
|
49
vendor/illuminate/database/Eloquent/Relations/MorphMany.php
vendored
Executable file
49
vendor/illuminate/database/Eloquent/Relations/MorphMany.php
vendored
Executable file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class MorphMany extends MorphOneOrMany
|
||||
{
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return ! is_null($this->getParentKey())
|
||||
? $this->query->get()
|
||||
: $this->related->newCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->related->newCollection());
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $this->matchMany($models, $results, $relation);
|
||||
}
|
||||
}
|
68
vendor/illuminate/database/Eloquent/Relations/MorphOne.php
vendored
Executable file
68
vendor/illuminate/database/Eloquent/Relations/MorphOne.php
vendored
Executable file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
|
||||
|
||||
class MorphOne extends MorphOneOrMany
|
||||
{
|
||||
use SupportsDefaultModels;
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
if (is_null($this->getParentKey())) {
|
||||
return $this->getDefaultFor($this->parent);
|
||||
}
|
||||
|
||||
return $this->query->first() ?: $this->getDefaultFor($this->parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->getDefaultFor($model));
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $this->matchOne($models, $results, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new related instance for the given model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function newRelatedInstanceFor(Model $parent)
|
||||
{
|
||||
return $this->related->newInstance()
|
||||
->setAttribute($this->getForeignKeyName(), $parent->{$this->localKey})
|
||||
->setAttribute($this->getMorphType(), $this->morphClass);
|
||||
}
|
||||
}
|
127
vendor/illuminate/database/Eloquent/Relations/MorphOneOrMany.php
vendored
Executable file
127
vendor/illuminate/database/Eloquent/Relations/MorphOneOrMany.php
vendored
Executable file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
abstract class MorphOneOrMany extends HasOneOrMany
|
||||
{
|
||||
/**
|
||||
* The foreign key type for the relationship.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphType;
|
||||
|
||||
/**
|
||||
* The class name of the parent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphClass;
|
||||
|
||||
/**
|
||||
* Create a new morph one or many relationship instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
* @param string $localKey
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $parent, $type, $id, $localKey)
|
||||
{
|
||||
$this->morphType = $type;
|
||||
|
||||
$this->morphClass = $parent->getMorphClass();
|
||||
|
||||
parent::__construct($query, $parent, $id, $localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base constraints on the relation query.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addConstraints()
|
||||
{
|
||||
if (static::$constraints) {
|
||||
parent::addConstraints();
|
||||
|
||||
$this->query->where($this->morphType, $this->morphClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
public function addEagerConstraints(array $models)
|
||||
{
|
||||
parent::addEagerConstraints($models);
|
||||
|
||||
$this->query->where($this->morphType, $this->morphClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the foreign ID and type for creating a related model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return void
|
||||
*/
|
||||
protected function setForeignAttributesForCreate(Model $model)
|
||||
{
|
||||
$model->{$this->getForeignKeyName()} = $this->getParentKey();
|
||||
|
||||
$model->{$this->getMorphType()} = $this->morphClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relationship query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
return parent::getRelationExistenceQuery($query, $parentQuery, $columns)->where(
|
||||
$query->qualifyColumn($this->getMorphType()), $this->morphClass
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key "type" name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedMorphType()
|
||||
{
|
||||
return $this->morphType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plain morph type name without the table.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMorphType()
|
||||
{
|
||||
return last(explode('.', $this->morphType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of the parent model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMorphClass()
|
||||
{
|
||||
return $this->morphClass;
|
||||
}
|
||||
}
|
162
vendor/illuminate/database/Eloquent/Relations/MorphPivot.php
vendored
Normal file
162
vendor/illuminate/database/Eloquent/Relations/MorphPivot.php
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class MorphPivot extends Pivot
|
||||
{
|
||||
/**
|
||||
* The type of the polymorphic relation.
|
||||
*
|
||||
* Explicitly define this so it's not included in saved attributes.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphType;
|
||||
|
||||
/**
|
||||
* The value of the polymorphic relation.
|
||||
*
|
||||
* Explicitly define this so it's not included in saved attributes.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphClass;
|
||||
|
||||
/**
|
||||
* Set the keys for a save update query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function setKeysForSaveQuery(Builder $query)
|
||||
{
|
||||
$query->where($this->morphType, $this->morphClass);
|
||||
|
||||
return parent::setKeysForSaveQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the pivot model record from the database.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
if (isset($this->attributes[$this->getKeyName()])) {
|
||||
return (int) parent::delete();
|
||||
}
|
||||
|
||||
if ($this->fireModelEvent('deleting') === false) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$query = $this->getDeleteQuery();
|
||||
|
||||
$query->where($this->morphType, $this->morphClass);
|
||||
|
||||
return tap($query->delete(), function () {
|
||||
$this->fireModelEvent('deleted', false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the morph type for the pivot.
|
||||
*
|
||||
* @param string $morphType
|
||||
* @return $this
|
||||
*/
|
||||
public function setMorphType($morphType)
|
||||
{
|
||||
$this->morphType = $morphType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the morph class for the pivot.
|
||||
*
|
||||
* @param string $morphClass
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphPivot
|
||||
*/
|
||||
public function setMorphClass($morphClass)
|
||||
{
|
||||
$this->morphClass = $morphClass;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the queueable identity for the entity.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getQueueableId()
|
||||
{
|
||||
if (isset($this->attributes[$this->getKeyName()])) {
|
||||
return $this->getKey();
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'%s:%s:%s:%s:%s:%s',
|
||||
$this->foreignKey, $this->getAttribute($this->foreignKey),
|
||||
$this->relatedKey, $this->getAttribute($this->relatedKey),
|
||||
$this->morphType, $this->morphClass
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new query to restore one or more models by their queueable IDs.
|
||||
*
|
||||
* @param array|int $ids
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function newQueryForRestoration($ids)
|
||||
{
|
||||
if (is_array($ids)) {
|
||||
return $this->newQueryForCollectionRestoration($ids);
|
||||
}
|
||||
|
||||
if (! Str::contains($ids, ':')) {
|
||||
return parent::newQueryForRestoration($ids);
|
||||
}
|
||||
|
||||
$segments = explode(':', $ids);
|
||||
|
||||
return $this->newQueryWithoutScopes()
|
||||
->where($segments[0], $segments[1])
|
||||
->where($segments[2], $segments[3])
|
||||
->where($segments[4], $segments[5]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new query to restore multiple models by their queueable IDs.
|
||||
*
|
||||
* @param array $ids
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function newQueryForCollectionRestoration(array $ids)
|
||||
{
|
||||
$ids = array_values($ids);
|
||||
|
||||
if (! Str::contains($ids[0], ':')) {
|
||||
return parent::newQueryForRestoration($ids);
|
||||
}
|
||||
|
||||
$query = $this->newQueryWithoutScopes();
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$segments = explode(':', $id);
|
||||
|
||||
$query->orWhere(function ($query) use ($segments) {
|
||||
return $query->where($segments[0], $segments[1])
|
||||
->where($segments[2], $segments[3])
|
||||
->where($segments[4], $segments[5]);
|
||||
});
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
353
vendor/illuminate/database/Eloquent/Relations/MorphTo.php
vendored
Normal file
353
vendor/illuminate/database/Eloquent/Relations/MorphTo.php
vendored
Normal file
@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class MorphTo extends BelongsTo
|
||||
{
|
||||
/**
|
||||
* The type of the polymorphic relation.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphType;
|
||||
|
||||
/**
|
||||
* The models whose relations are being eager loaded.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
protected $models;
|
||||
|
||||
/**
|
||||
* All of the models keyed by ID.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dictionary = [];
|
||||
|
||||
/**
|
||||
* A buffer of dynamic calls to query macros.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $macroBuffer = [];
|
||||
|
||||
/**
|
||||
* A map of relations to load for each individual morph type.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $morphableEagerLoads = [];
|
||||
|
||||
/**
|
||||
* A map of relationship counts to load for each individual morph type.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $morphableEagerLoadCounts = [];
|
||||
|
||||
/**
|
||||
* Create a new morph to relationship instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $foreignKey
|
||||
* @param string $ownerKey
|
||||
* @param string $type
|
||||
* @param string $relation
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $parent, $foreignKey, $ownerKey, $type, $relation)
|
||||
{
|
||||
$this->morphType = $type;
|
||||
|
||||
parent::__construct($query, $parent, $foreignKey, $ownerKey, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
public function addEagerConstraints(array $models)
|
||||
{
|
||||
$this->buildDictionary($this->models = Collection::make($models));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a dictionary with the models.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Collection $models
|
||||
* @return void
|
||||
*/
|
||||
protected function buildDictionary(Collection $models)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
if ($model->{$this->morphType}) {
|
||||
$this->dictionary[$model->{$this->morphType}][$model->{$this->foreignKey}][] = $model;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* Called via eager load method of Eloquent query builder.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getEager()
|
||||
{
|
||||
foreach (array_keys($this->dictionary) as $type) {
|
||||
$this->matchToMorphParents($type, $this->getResultsByType($type));
|
||||
}
|
||||
|
||||
return $this->models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the relation results for a type.
|
||||
*
|
||||
* @param string $type
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
protected function getResultsByType($type)
|
||||
{
|
||||
$instance = $this->createModelByType($type);
|
||||
|
||||
$ownerKey = $this->ownerKey ?? $instance->getKeyName();
|
||||
|
||||
$query = $this->replayMacros($instance->newQuery())
|
||||
->mergeConstraintsFrom($this->getQuery())
|
||||
->with(array_merge(
|
||||
$this->getQuery()->getEagerLoads(),
|
||||
(array) ($this->morphableEagerLoads[get_class($instance)] ?? [])
|
||||
))
|
||||
->withCount(
|
||||
(array) ($this->morphableEagerLoadCounts[get_class($instance)] ?? [])
|
||||
);
|
||||
|
||||
$whereIn = $this->whereInMethod($instance, $ownerKey);
|
||||
|
||||
return $query->{$whereIn}(
|
||||
$instance->getTable().'.'.$ownerKey, $this->gatherKeysByType($type)
|
||||
)->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather all of the foreign keys for a given type.
|
||||
*
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
protected function gatherKeysByType($type)
|
||||
{
|
||||
return array_keys($this->dictionary[$type]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new model instance by type.
|
||||
*
|
||||
* @param string $type
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function createModelByType($type)
|
||||
{
|
||||
$class = Model::getActualClassNameForMorph($type);
|
||||
|
||||
return tap(new $class, function ($instance) {
|
||||
if (! $instance->getConnectionName()) {
|
||||
$instance->setConnection($this->getConnection()->getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the results for a given type to their parents.
|
||||
*
|
||||
* @param string $type
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @return void
|
||||
*/
|
||||
protected function matchToMorphParents($type, Collection $results)
|
||||
{
|
||||
foreach ($results as $result) {
|
||||
$ownerKey = ! is_null($this->ownerKey) ? $result->{$this->ownerKey} : $result->getKey();
|
||||
|
||||
if (isset($this->dictionary[$type][$ownerKey])) {
|
||||
foreach ($this->dictionary[$type][$ownerKey] as $model) {
|
||||
$model->setRelation($this->relationName, $result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate the model instance to the given parent.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function associate($model)
|
||||
{
|
||||
$this->parent->setAttribute(
|
||||
$this->foreignKey, $model instanceof Model ? $model->getKey() : null
|
||||
);
|
||||
|
||||
$this->parent->setAttribute(
|
||||
$this->morphType, $model instanceof Model ? $model->getMorphClass() : null
|
||||
);
|
||||
|
||||
return $this->parent->setRelation($this->relationName, $model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dissociate previously associated model from the given parent.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function dissociate()
|
||||
{
|
||||
$this->parent->setAttribute($this->foreignKey, null);
|
||||
|
||||
$this->parent->setAttribute($this->morphType, null);
|
||||
|
||||
return $this->parent->setRelation($this->relationName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch all of the related models for the relationship.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function touch()
|
||||
{
|
||||
if (! is_null($this->child->{$this->foreignKey})) {
|
||||
parent::touch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new related instance for the given model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected function newRelatedInstanceFor(Model $parent)
|
||||
{
|
||||
return $parent->{$this->getRelationName()}()->getRelated()->newInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key "type" name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMorphType()
|
||||
{
|
||||
return $this->morphType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dictionary used by the relationship.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDictionary()
|
||||
{
|
||||
return $this->dictionary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify which relations to load for a given morph type.
|
||||
*
|
||||
* @param array $with
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
public function morphWith(array $with)
|
||||
{
|
||||
$this->morphableEagerLoads = array_merge(
|
||||
$this->morphableEagerLoads, $with
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify which relationship counts to load for a given morph type.
|
||||
*
|
||||
* @param array $withCount
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
public function morphWithCount(array $withCount)
|
||||
{
|
||||
$this->morphableEagerLoadCounts = array_merge(
|
||||
$this->morphableEagerLoadCounts, $withCount
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replay stored macro calls on the actual related instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function replayMacros(Builder $query)
|
||||
{
|
||||
foreach ($this->macroBuffer as $macro) {
|
||||
$query->{$macro['method']}(...$macro['parameters']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dynamic method calls to the relationship.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
try {
|
||||
$result = parent::__call($method, $parameters);
|
||||
|
||||
if (in_array($method, ['select', 'selectRaw', 'selectSub', 'addSelect', 'withoutGlobalScopes'])) {
|
||||
$this->macroBuffer[] = compact('method', 'parameters');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
// If we tried to call a method that does not exist on the parent Builder instance,
|
||||
// we'll assume that we want to call a query macro (e.g. withTrashed) that only
|
||||
// exists on related models. We will just store the call and replay it later.
|
||||
catch (BadMethodCallException $e) {
|
||||
$this->macroBuffer[] = compact('method', 'parameters');
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
}
|
209
vendor/illuminate/database/Eloquent/Relations/MorphToMany.php
vendored
Normal file
209
vendor/illuminate/database/Eloquent/Relations/MorphToMany.php
vendored
Normal file
@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class MorphToMany extends BelongsToMany
|
||||
{
|
||||
/**
|
||||
* The type of the polymorphic relation.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphType;
|
||||
|
||||
/**
|
||||
* The class name of the morph type constraint.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphClass;
|
||||
|
||||
/**
|
||||
* Indicates if we are connecting the inverse of the relation.
|
||||
*
|
||||
* This primarily affects the morphClass constraint.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $inverse;
|
||||
|
||||
/**
|
||||
* Create a new morph to many relationship instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $name
|
||||
* @param string $table
|
||||
* @param string $foreignPivotKey
|
||||
* @param string $relatedPivotKey
|
||||
* @param string $parentKey
|
||||
* @param string $relatedKey
|
||||
* @param string|null $relationName
|
||||
* @param bool $inverse
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $parent, $name, $table, $foreignPivotKey,
|
||||
$relatedPivotKey, $parentKey, $relatedKey, $relationName = null, $inverse = false)
|
||||
{
|
||||
$this->inverse = $inverse;
|
||||
$this->morphType = $name.'_type';
|
||||
$this->morphClass = $inverse ? $query->getModel()->getMorphClass() : $parent->getMorphClass();
|
||||
|
||||
parent::__construct(
|
||||
$query, $parent, $table, $foreignPivotKey,
|
||||
$relatedPivotKey, $parentKey, $relatedKey, $relationName
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the where clause for the relation query.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function addWhereConstraints()
|
||||
{
|
||||
parent::addWhereConstraints();
|
||||
|
||||
$this->query->where($this->table.'.'.$this->morphType, $this->morphClass);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
public function addEagerConstraints(array $models)
|
||||
{
|
||||
parent::addEagerConstraints($models);
|
||||
|
||||
$this->query->where($this->table.'.'.$this->morphType, $this->morphClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new pivot attachment record.
|
||||
*
|
||||
* @param int $id
|
||||
* @param bool $timed
|
||||
* @return array
|
||||
*/
|
||||
protected function baseAttachRecord($id, $timed)
|
||||
{
|
||||
return Arr::add(
|
||||
parent::baseAttachRecord($id, $timed), $this->morphType, $this->morphClass
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship count query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
return parent::getRelationExistenceQuery($query, $parentQuery, $columns)->where(
|
||||
$this->table.'.'.$this->morphType, $this->morphClass
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pivot models that are currently attached.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function getCurrentlyAttachedPivots()
|
||||
{
|
||||
return parent::getCurrentlyAttachedPivots()->map(function ($record) {
|
||||
return $record instanceof MorphPivot
|
||||
? $record->setMorphType($this->morphType)
|
||||
->setMorphClass($this->morphClass)
|
||||
: $record;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new query builder for the pivot table.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function newPivotQuery()
|
||||
{
|
||||
return parent::newPivotQuery()->where($this->morphType, $this->morphClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new pivot model instance.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param bool $exists
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Pivot
|
||||
*/
|
||||
public function newPivot(array $attributes = [], $exists = false)
|
||||
{
|
||||
$using = $this->using;
|
||||
|
||||
$pivot = $using ? $using::fromRawAttributes($this->parent, $attributes, $this->table, $exists)
|
||||
: MorphPivot::fromAttributes($this->parent, $attributes, $this->table, $exists);
|
||||
|
||||
$pivot->setPivotKeys($this->foreignPivotKey, $this->relatedPivotKey)
|
||||
->setMorphType($this->morphType)
|
||||
->setMorphClass($this->morphClass);
|
||||
|
||||
return $pivot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pivot columns for the relation.
|
||||
*
|
||||
* "pivot_" is prefixed at each column for easy removal later.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function aliasedPivotColumns()
|
||||
{
|
||||
$defaults = [$this->foreignPivotKey, $this->relatedPivotKey, $this->morphType];
|
||||
|
||||
return collect(array_merge($defaults, $this->pivotColumns))->map(function ($column) {
|
||||
return $this->table.'.'.$column.' as pivot_'.$column;
|
||||
})->unique()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key "type" name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMorphType()
|
||||
{
|
||||
return $this->morphType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of the parent model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMorphClass()
|
||||
{
|
||||
return $this->morphClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the indicator for a reverse relationship.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getInverse()
|
||||
{
|
||||
return $this->inverse;
|
||||
}
|
||||
}
|
25
vendor/illuminate/database/Eloquent/Relations/Pivot.php
vendored
Executable file
25
vendor/illuminate/database/Eloquent/Relations/Pivot.php
vendored
Executable file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\AsPivot;
|
||||
|
||||
class Pivot extends Model
|
||||
{
|
||||
use AsPivot;
|
||||
|
||||
/**
|
||||
* Indicates if the IDs are auto-incrementing.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $incrementing = false;
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = [];
|
||||
}
|
403
vendor/illuminate/database/Eloquent/Relations/Relation.php
vendored
Executable file
403
vendor/illuminate/database/Eloquent/Relations/Relation.php
vendored
Executable file
@ -0,0 +1,403 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Traits\ForwardsCalls;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
|
||||
/**
|
||||
* @mixin \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
abstract class Relation
|
||||
{
|
||||
use ForwardsCalls, Macroable {
|
||||
__call as macroCall;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Eloquent query builder instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected $query;
|
||||
|
||||
/**
|
||||
* The parent model instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected $parent;
|
||||
|
||||
/**
|
||||
* The related model instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected $related;
|
||||
|
||||
/**
|
||||
* Indicates if the relation is adding constraints.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $constraints = true;
|
||||
|
||||
/**
|
||||
* An array to map class names to their morph names in database.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $morphMap = [];
|
||||
|
||||
/**
|
||||
* Create a new relation instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $parent)
|
||||
{
|
||||
$this->query = $query;
|
||||
$this->parent = $parent;
|
||||
$this->related = $query->getModel();
|
||||
|
||||
$this->addConstraints();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a callback with constraints disabled on the relation.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public static function noConstraints(Closure $callback)
|
||||
{
|
||||
$previous = static::$constraints;
|
||||
|
||||
static::$constraints = false;
|
||||
|
||||
// When resetting the relation where clause, we want to shift the first element
|
||||
// off of the bindings, leaving only the constraints that the developers put
|
||||
// as "extra" on the relationships, and not original relation constraints.
|
||||
try {
|
||||
return $callback();
|
||||
} finally {
|
||||
static::$constraints = $previous;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base constraints on the relation query.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract public function addConstraints();
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
abstract public function addEagerConstraints(array $models);
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
abstract public function initRelation(array $models, $relation);
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
abstract public function match(array $models, Collection $results, $relation);
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function getResults();
|
||||
|
||||
/**
|
||||
* Get the relationship for eager loading.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getEager()
|
||||
{
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as a "select" statement.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function get($columns = ['*'])
|
||||
{
|
||||
return $this->query->get($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch all of the related models for the relationship.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function touch()
|
||||
{
|
||||
$model = $this->getRelated();
|
||||
|
||||
if (! $model::isIgnoringTouch()) {
|
||||
$this->rawUpdate([
|
||||
$model->getUpdatedAtColumn() => $model->freshTimestampString(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a raw update against the base query.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return int
|
||||
*/
|
||||
public function rawUpdate(array $attributes = [])
|
||||
{
|
||||
return $this->query->withoutGlobalScopes()->update($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship count query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceCountQuery(Builder $query, Builder $parentQuery)
|
||||
{
|
||||
return $this->getRelationExistenceQuery(
|
||||
$query, $parentQuery, new Expression('count(*)')
|
||||
)->setBindings([], 'select');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for an internal relationship existence query.
|
||||
*
|
||||
* Essentially, these queries compare on column names like whereColumn.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
return $query->select($columns)->whereColumn(
|
||||
$this->getQualifiedParentKeyName(), '=', $this->getExistenceCompareKey()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the primary keys for an array of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string|null $key
|
||||
* @return array
|
||||
*/
|
||||
protected function getKeys(array $models, $key = null)
|
||||
{
|
||||
return collect($models)->map(function ($value) use ($key) {
|
||||
return $key ? $value->getAttribute($key) : $value->getKey();
|
||||
})->values()->unique(null, true)->sort()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the underlying query for the relation.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getQuery()
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base query builder driving the Eloquent builder.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function getBaseQuery()
|
||||
{
|
||||
return $this->query->getQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent model of the relation.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified parent key name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedParentKeyName()
|
||||
{
|
||||
return $this->parent->getQualifiedKeyName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the related model of the relation.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function getRelated()
|
||||
{
|
||||
return $this->related;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "created at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createdAt()
|
||||
{
|
||||
return $this->parent->getCreatedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "updated at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function updatedAt()
|
||||
{
|
||||
return $this->parent->getUpdatedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the related model's "updated at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function relatedUpdatedAt()
|
||||
{
|
||||
return $this->related->getUpdatedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "where in" method for eager loading.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
protected function whereInMethod(Model $model, $key)
|
||||
{
|
||||
return $model->getKeyName() === last(explode('.', $key))
|
||||
&& in_array($model->getKeyType(), ['int', 'integer'])
|
||||
? 'whereIntegerInRaw'
|
||||
: 'whereIn';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or get the morph map for polymorphic relations.
|
||||
*
|
||||
* @param array|null $map
|
||||
* @param bool $merge
|
||||
* @return array
|
||||
*/
|
||||
public static function morphMap(array $map = null, $merge = true)
|
||||
{
|
||||
$map = static::buildMorphMapFromModels($map);
|
||||
|
||||
if (is_array($map)) {
|
||||
static::$morphMap = $merge && static::$morphMap
|
||||
? $map + static::$morphMap : $map;
|
||||
}
|
||||
|
||||
return static::$morphMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a table-keyed array from model class names.
|
||||
*
|
||||
* @param string[]|null $models
|
||||
* @return array|null
|
||||
*/
|
||||
protected static function buildMorphMapFromModels(array $models = null)
|
||||
{
|
||||
if (is_null($models) || Arr::isAssoc($models)) {
|
||||
return $models;
|
||||
}
|
||||
|
||||
return array_combine(array_map(function ($model) {
|
||||
return (new $model)->getTable();
|
||||
}, $models), $models);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model associated with a custom polymorphic type.
|
||||
*
|
||||
* @param string $alias
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getMorphedModel($alias)
|
||||
{
|
||||
return static::$morphMap[$alias] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dynamic method calls to the relationship.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
if (static::hasMacro($method)) {
|
||||
return $this->macroCall($method, $parameters);
|
||||
}
|
||||
|
||||
$result = $this->forwardCallTo($this->query, $method, $parameters);
|
||||
|
||||
if ($result === $this->query) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a clone of the underlying query builder when cloning.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$this->query = clone $this->query;
|
||||
}
|
||||
}
|
15
vendor/illuminate/database/Eloquent/Scope.php
vendored
Normal file
15
vendor/illuminate/database/Eloquent/Scope.php
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
interface Scope
|
||||
{
|
||||
/**
|
||||
* Apply the scope to a given Eloquent query builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return void
|
||||
*/
|
||||
public function apply(Builder $builder, Model $model);
|
||||
}
|
199
vendor/illuminate/database/Eloquent/SoftDeletes.php
vendored
Normal file
199
vendor/illuminate/database/Eloquent/SoftDeletes.php
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
/**
|
||||
* @method static static|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder withTrashed()
|
||||
* @method static static|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder onlyTrashed()
|
||||
* @method static static|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder withoutTrashed()
|
||||
*/
|
||||
trait SoftDeletes
|
||||
{
|
||||
/**
|
||||
* Indicates if the model is currently force deleting.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $forceDeleting = false;
|
||||
|
||||
/**
|
||||
* Boot the soft deleting trait for a model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function bootSoftDeletes()
|
||||
{
|
||||
static::addGlobalScope(new SoftDeletingScope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the soft deleting trait for an instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initializeSoftDeletes()
|
||||
{
|
||||
$this->dates[] = $this->getDeletedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a hard delete on a soft deleted model.
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function forceDelete()
|
||||
{
|
||||
$this->forceDeleting = true;
|
||||
|
||||
return tap($this->delete(), function ($deleted) {
|
||||
$this->forceDeleting = false;
|
||||
|
||||
if ($deleted) {
|
||||
$this->fireModelEvent('forceDeleted', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the actual delete query on this model instance.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function performDeleteOnModel()
|
||||
{
|
||||
if ($this->forceDeleting) {
|
||||
$this->exists = false;
|
||||
|
||||
return $this->setKeysForSaveQuery($this->newModelQuery())->forceDelete();
|
||||
}
|
||||
|
||||
return $this->runSoftDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the actual delete query on this model instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function runSoftDelete()
|
||||
{
|
||||
$query = $this->setKeysForSaveQuery($this->newModelQuery());
|
||||
|
||||
$time = $this->freshTimestamp();
|
||||
|
||||
$columns = [$this->getDeletedAtColumn() => $this->fromDateTime($time)];
|
||||
|
||||
$this->{$this->getDeletedAtColumn()} = $time;
|
||||
|
||||
if ($this->timestamps && ! is_null($this->getUpdatedAtColumn())) {
|
||||
$this->{$this->getUpdatedAtColumn()} = $time;
|
||||
|
||||
$columns[$this->getUpdatedAtColumn()] = $this->fromDateTime($time);
|
||||
}
|
||||
|
||||
$query->update($columns);
|
||||
|
||||
$this->syncOriginalAttributes(array_keys($columns));
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore a soft-deleted model instance.
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function restore()
|
||||
{
|
||||
// If the restoring event does not return false, we will proceed with this
|
||||
// restore operation. Otherwise, we bail out so the developer will stop
|
||||
// the restore totally. We will clear the deleted timestamp and save.
|
||||
if ($this->fireModelEvent('restoring') === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->{$this->getDeletedAtColumn()} = null;
|
||||
|
||||
// Once we have saved the model, we will fire the "restored" event so this
|
||||
// developer will do anything they need to after a restore operation is
|
||||
// totally finished. Then we will return the result of the save call.
|
||||
$this->exists = true;
|
||||
|
||||
$result = $this->save();
|
||||
|
||||
$this->fireModelEvent('restored', false);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model instance has been soft-deleted.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function trashed()
|
||||
{
|
||||
return ! is_null($this->{$this->getDeletedAtColumn()});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a "restoring" model event callback with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function restoring($callback)
|
||||
{
|
||||
static::registerModelEvent('restoring', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a "restored" model event callback with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function restored($callback)
|
||||
{
|
||||
static::registerModelEvent('restored', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a "forceDeleted" model event callback with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function forceDeleted($callback)
|
||||
{
|
||||
static::registerModelEvent('forceDeleted', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model is currently force deleting.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isForceDeleting()
|
||||
{
|
||||
return $this->forceDeleting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "deleted at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDeletedAtColumn()
|
||||
{
|
||||
return defined('static::DELETED_AT') ? static::DELETED_AT : 'deleted_at';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified "deleted at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedDeletedAtColumn()
|
||||
{
|
||||
return $this->qualifyColumn($this->getDeletedAtColumn());
|
||||
}
|
||||
}
|
131
vendor/illuminate/database/Eloquent/SoftDeletingScope.php
vendored
Normal file
131
vendor/illuminate/database/Eloquent/SoftDeletingScope.php
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
class SoftDeletingScope implements Scope
|
||||
{
|
||||
/**
|
||||
* All of the extensions to be added to the builder.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $extensions = ['Restore', 'WithTrashed', 'WithoutTrashed', 'OnlyTrashed'];
|
||||
|
||||
/**
|
||||
* Apply the scope to a given Eloquent query builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return void
|
||||
*/
|
||||
public function apply(Builder $builder, Model $model)
|
||||
{
|
||||
$builder->whereNull($model->getQualifiedDeletedAtColumn());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the query builder with the needed functions.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
public function extend(Builder $builder)
|
||||
{
|
||||
foreach ($this->extensions as $extension) {
|
||||
$this->{"add{$extension}"}($builder);
|
||||
}
|
||||
|
||||
$builder->onDelete(function (Builder $builder) {
|
||||
$column = $this->getDeletedAtColumn($builder);
|
||||
|
||||
return $builder->update([
|
||||
$column => $builder->getModel()->freshTimestampString(),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "deleted at" column for the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return string
|
||||
*/
|
||||
protected function getDeletedAtColumn(Builder $builder)
|
||||
{
|
||||
if (count((array) $builder->getQuery()->joins) > 0) {
|
||||
return $builder->getModel()->getQualifiedDeletedAtColumn();
|
||||
}
|
||||
|
||||
return $builder->getModel()->getDeletedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the restore extension to the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
protected function addRestore(Builder $builder)
|
||||
{
|
||||
$builder->macro('restore', function (Builder $builder) {
|
||||
$builder->withTrashed();
|
||||
|
||||
return $builder->update([$builder->getModel()->getDeletedAtColumn() => null]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the with-trashed extension to the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
protected function addWithTrashed(Builder $builder)
|
||||
{
|
||||
$builder->macro('withTrashed', function (Builder $builder, $withTrashed = true) {
|
||||
if (! $withTrashed) {
|
||||
return $builder->withoutTrashed();
|
||||
}
|
||||
|
||||
return $builder->withoutGlobalScope($this);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the without-trashed extension to the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
protected function addWithoutTrashed(Builder $builder)
|
||||
{
|
||||
$builder->macro('withoutTrashed', function (Builder $builder) {
|
||||
$model = $builder->getModel();
|
||||
|
||||
$builder->withoutGlobalScope($this)->whereNull(
|
||||
$model->getQualifiedDeletedAtColumn()
|
||||
);
|
||||
|
||||
return $builder;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the only-trashed extension to the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
protected function addOnlyTrashed(Builder $builder)
|
||||
{
|
||||
$builder->macro('onlyTrashed', function (Builder $builder) {
|
||||
$model = $builder->getModel();
|
||||
|
||||
$builder->withoutGlobalScope($this)->whereNotNull(
|
||||
$model->getQualifiedDeletedAtColumn()
|
||||
);
|
||||
|
||||
return $builder;
|
||||
});
|
||||
}
|
||||
}
|
32
vendor/illuminate/database/Events/ConnectionEvent.php
vendored
Normal file
32
vendor/illuminate/database/Events/ConnectionEvent.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
abstract class ConnectionEvent
|
||||
{
|
||||
/**
|
||||
* The name of the connection.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $connectionName;
|
||||
|
||||
/**
|
||||
* The database connection instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connection
|
||||
*/
|
||||
public $connection;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
$this->connectionName = $connection->getName();
|
||||
}
|
||||
}
|
8
vendor/illuminate/database/Events/MigrationEnded.php
vendored
Normal file
8
vendor/illuminate/database/Events/MigrationEnded.php
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
class MigrationEnded extends MigrationEvent
|
||||
{
|
||||
//
|
||||
}
|
36
vendor/illuminate/database/Events/MigrationEvent.php
vendored
Normal file
36
vendor/illuminate/database/Events/MigrationEvent.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
use Illuminate\Contracts\Database\Events\MigrationEvent as MigrationEventContract;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
abstract class MigrationEvent implements MigrationEventContract
|
||||
{
|
||||
/**
|
||||
* An migration instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\Migration
|
||||
*/
|
||||
public $migration;
|
||||
|
||||
/**
|
||||
* The migration method that was called.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $method;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\Migration $migration
|
||||
* @param string $method
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Migration $migration, $method)
|
||||
{
|
||||
$this->method = $method;
|
||||
$this->migration = $migration;
|
||||
}
|
||||
}
|
8
vendor/illuminate/database/Events/MigrationStarted.php
vendored
Normal file
8
vendor/illuminate/database/Events/MigrationStarted.php
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
class MigrationStarted extends MigrationEvent
|
||||
{
|
||||
//
|
||||
}
|
10
vendor/illuminate/database/Events/MigrationsEnded.php
vendored
Normal file
10
vendor/illuminate/database/Events/MigrationsEnded.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
use Illuminate\Contracts\Database\Events\MigrationEvent as MigrationEventContract;
|
||||
|
||||
class MigrationsEnded implements MigrationEventContract
|
||||
{
|
||||
//
|
||||
}
|
10
vendor/illuminate/database/Events/MigrationsStarted.php
vendored
Normal file
10
vendor/illuminate/database/Events/MigrationsStarted.php
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
use Illuminate\Contracts\Database\Events\MigrationEvent as MigrationEventContract;
|
||||
|
||||
class MigrationsStarted implements MigrationEventContract
|
||||
{
|
||||
//
|
||||
}
|
24
vendor/illuminate/database/Events/NoPendingMigrations.php
vendored
Normal file
24
vendor/illuminate/database/Events/NoPendingMigrations.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
class NoPendingMigrations
|
||||
{
|
||||
/**
|
||||
* The migration method that was called.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $method;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param string $method
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($method)
|
||||
{
|
||||
$this->method = $method;
|
||||
}
|
||||
}
|
59
vendor/illuminate/database/Events/QueryExecuted.php
vendored
Normal file
59
vendor/illuminate/database/Events/QueryExecuted.php
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
class QueryExecuted
|
||||
{
|
||||
/**
|
||||
* The SQL query that was executed.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $sql;
|
||||
|
||||
/**
|
||||
* The array of query bindings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $bindings;
|
||||
|
||||
/**
|
||||
* The number of milliseconds it took to execute the query.
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
public $time;
|
||||
|
||||
/**
|
||||
* The database connection instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connection
|
||||
*/
|
||||
public $connection;
|
||||
|
||||
/**
|
||||
* The database connection name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $connectionName;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param string $sql
|
||||
* @param array $bindings
|
||||
* @param float|null $time
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($sql, $bindings, $time, $connection)
|
||||
{
|
||||
$this->sql = $sql;
|
||||
$this->time = $time;
|
||||
$this->bindings = $bindings;
|
||||
$this->connection = $connection;
|
||||
$this->connectionName = $connection->getName();
|
||||
}
|
||||
}
|
33
vendor/illuminate/database/Events/StatementPrepared.php
vendored
Normal file
33
vendor/illuminate/database/Events/StatementPrepared.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
class StatementPrepared
|
||||
{
|
||||
/**
|
||||
* The database connection instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connection
|
||||
*/
|
||||
public $connection;
|
||||
|
||||
/**
|
||||
* The PDO statement.
|
||||
*
|
||||
* @var \PDOStatement
|
||||
*/
|
||||
public $statement;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param \PDOStatement $statement
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($connection, $statement)
|
||||
{
|
||||
$this->statement = $statement;
|
||||
$this->connection = $connection;
|
||||
}
|
||||
}
|
8
vendor/illuminate/database/Events/TransactionBeginning.php
vendored
Normal file
8
vendor/illuminate/database/Events/TransactionBeginning.php
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
class TransactionBeginning extends ConnectionEvent
|
||||
{
|
||||
//
|
||||
}
|
8
vendor/illuminate/database/Events/TransactionCommitted.php
vendored
Normal file
8
vendor/illuminate/database/Events/TransactionCommitted.php
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
class TransactionCommitted extends ConnectionEvent
|
||||
{
|
||||
//
|
||||
}
|
8
vendor/illuminate/database/Events/TransactionRolledBack.php
vendored
Normal file
8
vendor/illuminate/database/Events/TransactionRolledBack.php
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
class TransactionRolledBack extends ConnectionEvent
|
||||
{
|
||||
//
|
||||
}
|
221
vendor/illuminate/database/Grammar.php
vendored
Executable file
221
vendor/illuminate/database/Grammar.php
vendored
Executable file
@ -0,0 +1,221 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
|
||||
abstract class Grammar
|
||||
{
|
||||
use Macroable;
|
||||
|
||||
/**
|
||||
* The grammar table prefix.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $tablePrefix = '';
|
||||
|
||||
/**
|
||||
* Wrap an array of values.
|
||||
*
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
public function wrapArray(array $values)
|
||||
{
|
||||
return array_map([$this, 'wrap'], $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a table in keyword identifiers.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Expression|string $table
|
||||
* @return string
|
||||
*/
|
||||
public function wrapTable($table)
|
||||
{
|
||||
if (! $this->isExpression($table)) {
|
||||
return $this->wrap($this->tablePrefix.$table, true);
|
||||
}
|
||||
|
||||
return $this->getValue($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a value in keyword identifiers.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Expression|string $value
|
||||
* @param bool $prefixAlias
|
||||
* @return string
|
||||
*/
|
||||
public function wrap($value, $prefixAlias = false)
|
||||
{
|
||||
if ($this->isExpression($value)) {
|
||||
return $this->getValue($value);
|
||||
}
|
||||
|
||||
// If the value being wrapped has a column alias we will need to separate out
|
||||
// the pieces so we can wrap each of the segments of the expression on its
|
||||
// own, and then join these both back together using the "as" connector.
|
||||
if (stripos($value, ' as ') !== false) {
|
||||
return $this->wrapAliasedValue($value, $prefixAlias);
|
||||
}
|
||||
|
||||
return $this->wrapSegments(explode('.', $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a value that has an alias.
|
||||
*
|
||||
* @param string $value
|
||||
* @param bool $prefixAlias
|
||||
* @return string
|
||||
*/
|
||||
protected function wrapAliasedValue($value, $prefixAlias = false)
|
||||
{
|
||||
$segments = preg_split('/\s+as\s+/i', $value);
|
||||
|
||||
// If we are wrapping a table we need to prefix the alias with the table prefix
|
||||
// as well in order to generate proper syntax. If this is a column of course
|
||||
// no prefix is necessary. The condition will be true when from wrapTable.
|
||||
if ($prefixAlias) {
|
||||
$segments[1] = $this->tablePrefix.$segments[1];
|
||||
}
|
||||
|
||||
return $this->wrap($segments[0]).' as '.$this->wrapValue($segments[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the given value segments.
|
||||
*
|
||||
* @param array $segments
|
||||
* @return string
|
||||
*/
|
||||
protected function wrapSegments($segments)
|
||||
{
|
||||
return collect($segments)->map(function ($segment, $key) use ($segments) {
|
||||
return $key == 0 && count($segments) > 1
|
||||
? $this->wrapTable($segment)
|
||||
: $this->wrapValue($segment);
|
||||
})->implode('.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a single string in keyword identifiers.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function wrapValue($value)
|
||||
{
|
||||
if ($value !== '*') {
|
||||
return '"'.str_replace('"', '""', $value).'"';
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array of column names into a delimited string.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return string
|
||||
*/
|
||||
public function columnize(array $columns)
|
||||
{
|
||||
return implode(', ', array_map([$this, 'wrap'], $columns));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create query parameter place-holders for an array.
|
||||
*
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
public function parameterize(array $values)
|
||||
{
|
||||
return implode(', ', array_map([$this, 'parameter'], $values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the appropriate query parameter place-holder for a value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
public function parameter($value)
|
||||
{
|
||||
return $this->isExpression($value) ? $this->getValue($value) : '?';
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote the given string literal.
|
||||
*
|
||||
* @param string|array $value
|
||||
* @return string
|
||||
*/
|
||||
public function quoteString($value)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
return implode(', ', array_map([$this, __FUNCTION__], $value));
|
||||
}
|
||||
|
||||
return "'$value'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given value is a raw expression.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function isExpression($value)
|
||||
{
|
||||
return $value instanceof Expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a raw expression.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Expression $expression
|
||||
* @return string
|
||||
*/
|
||||
public function getValue($expression)
|
||||
{
|
||||
return $expression->getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the format for database stored dates.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateFormat()
|
||||
{
|
||||
return 'Y-m-d H:i:s';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the grammar's table prefix.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTablePrefix()
|
||||
{
|
||||
return $this->tablePrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the grammar's table prefix.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @return $this
|
||||
*/
|
||||
public function setTablePrefix($prefix)
|
||||
{
|
||||
$this->tablePrefix = $prefix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
21
vendor/illuminate/database/LICENSE.md
vendored
Normal file
21
vendor/illuminate/database/LICENSE.md
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Taylor Otwell
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
225
vendor/illuminate/database/MigrationServiceProvider.php
vendored
Executable file
225
vendor/illuminate/database/MigrationServiceProvider.php
vendored
Executable file
@ -0,0 +1,225 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Illuminate\Contracts\Support\DeferrableProvider;
|
||||
use Illuminate\Database\Console\Migrations\FreshCommand;
|
||||
use Illuminate\Database\Console\Migrations\InstallCommand;
|
||||
use Illuminate\Database\Console\Migrations\MigrateCommand;
|
||||
use Illuminate\Database\Console\Migrations\MigrateMakeCommand;
|
||||
use Illuminate\Database\Console\Migrations\RefreshCommand;
|
||||
use Illuminate\Database\Console\Migrations\ResetCommand;
|
||||
use Illuminate\Database\Console\Migrations\RollbackCommand;
|
||||
use Illuminate\Database\Console\Migrations\StatusCommand;
|
||||
use Illuminate\Database\Migrations\DatabaseMigrationRepository;
|
||||
use Illuminate\Database\Migrations\MigrationCreator;
|
||||
use Illuminate\Database\Migrations\Migrator;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class MigrationServiceProvider extends ServiceProvider implements DeferrableProvider
|
||||
{
|
||||
/**
|
||||
* The commands to be registered.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
'Migrate' => 'command.migrate',
|
||||
'MigrateFresh' => 'command.migrate.fresh',
|
||||
'MigrateInstall' => 'command.migrate.install',
|
||||
'MigrateRefresh' => 'command.migrate.refresh',
|
||||
'MigrateReset' => 'command.migrate.reset',
|
||||
'MigrateRollback' => 'command.migrate.rollback',
|
||||
'MigrateStatus' => 'command.migrate.status',
|
||||
'MigrateMake' => 'command.migrate.make',
|
||||
];
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->registerRepository();
|
||||
|
||||
$this->registerMigrator();
|
||||
|
||||
$this->registerCreator();
|
||||
|
||||
$this->registerCommands($this->commands);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the migration repository service.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerRepository()
|
||||
{
|
||||
$this->app->singleton('migration.repository', function ($app) {
|
||||
$table = $app['config']['database.migrations'];
|
||||
|
||||
return new DatabaseMigrationRepository($app['db'], $table);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the migrator service.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerMigrator()
|
||||
{
|
||||
// The migrator is responsible for actually running and rollback the migration
|
||||
// files in the application. We'll pass in our database connection resolver
|
||||
// so the migrator can resolve any of these connections when it needs to.
|
||||
$this->app->singleton('migrator', function ($app) {
|
||||
$repository = $app['migration.repository'];
|
||||
|
||||
return new Migrator($repository, $app['db'], $app['files'], $app['events']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the migration creator.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerCreator()
|
||||
{
|
||||
$this->app->singleton('migration.creator', function ($app) {
|
||||
return new MigrationCreator($app['files'], $app->basePath('stubs'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given commands.
|
||||
*
|
||||
* @param array $commands
|
||||
* @return void
|
||||
*/
|
||||
protected function registerCommands(array $commands)
|
||||
{
|
||||
foreach (array_keys($commands) as $command) {
|
||||
$this->{"register{$command}Command"}();
|
||||
}
|
||||
|
||||
$this->commands(array_values($commands));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerMigrateCommand()
|
||||
{
|
||||
$this->app->singleton('command.migrate', function ($app) {
|
||||
return new MigrateCommand($app['migrator']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerMigrateFreshCommand()
|
||||
{
|
||||
$this->app->singleton('command.migrate.fresh', function () {
|
||||
return new FreshCommand;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerMigrateInstallCommand()
|
||||
{
|
||||
$this->app->singleton('command.migrate.install', function ($app) {
|
||||
return new InstallCommand($app['migration.repository']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerMigrateMakeCommand()
|
||||
{
|
||||
$this->app->singleton('command.migrate.make', function ($app) {
|
||||
// Once we have the migration creator registered, we will create the command
|
||||
// and inject the creator. The creator is responsible for the actual file
|
||||
// creation of the migrations, and may be extended by these developers.
|
||||
$creator = $app['migration.creator'];
|
||||
|
||||
$composer = $app['composer'];
|
||||
|
||||
return new MigrateMakeCommand($creator, $composer);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerMigrateRefreshCommand()
|
||||
{
|
||||
$this->app->singleton('command.migrate.refresh', function () {
|
||||
return new RefreshCommand;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerMigrateResetCommand()
|
||||
{
|
||||
$this->app->singleton('command.migrate.reset', function ($app) {
|
||||
return new ResetCommand($app['migrator']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerMigrateRollbackCommand()
|
||||
{
|
||||
$this->app->singleton('command.migrate.rollback', function ($app) {
|
||||
return new RollbackCommand($app['migrator']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerMigrateStatusCommand()
|
||||
{
|
||||
$this->app->singleton('command.migrate.status', function ($app) {
|
||||
return new StatusCommand($app['migrator']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provides()
|
||||
{
|
||||
return array_merge([
|
||||
'migrator', 'migration.repository', 'migration.creator',
|
||||
], array_values($this->commands));
|
||||
}
|
||||
}
|
212
vendor/illuminate/database/Migrations/DatabaseMigrationRepository.php
vendored
Executable file
212
vendor/illuminate/database/Migrations/DatabaseMigrationRepository.php
vendored
Executable file
@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Migrations;
|
||||
|
||||
use Illuminate\Database\ConnectionResolverInterface as Resolver;
|
||||
|
||||
class DatabaseMigrationRepository implements MigrationRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* The database connection resolver instance.
|
||||
*
|
||||
* @var \Illuminate\Database\ConnectionResolverInterface
|
||||
*/
|
||||
protected $resolver;
|
||||
|
||||
/**
|
||||
* The name of the migration table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* The name of the database connection to use.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* Create a new database migration repository instance.
|
||||
*
|
||||
* @param \Illuminate\Database\ConnectionResolverInterface $resolver
|
||||
* @param string $table
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Resolver $resolver, $table)
|
||||
{
|
||||
$this->table = $table;
|
||||
$this->resolver = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the completed migrations.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRan()
|
||||
{
|
||||
return $this->table()
|
||||
->orderBy('batch', 'asc')
|
||||
->orderBy('migration', 'asc')
|
||||
->pluck('migration')->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of migrations.
|
||||
*
|
||||
* @param int $steps
|
||||
* @return array
|
||||
*/
|
||||
public function getMigrations($steps)
|
||||
{
|
||||
$query = $this->table()->where('batch', '>=', '1');
|
||||
|
||||
return $query->orderBy('batch', 'desc')
|
||||
->orderBy('migration', 'desc')
|
||||
->take($steps)->get()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last migration batch.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLast()
|
||||
{
|
||||
$query = $this->table()->where('batch', $this->getLastBatchNumber());
|
||||
|
||||
return $query->orderBy('migration', 'desc')->get()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the completed migrations with their batch numbers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMigrationBatches()
|
||||
{
|
||||
return $this->table()
|
||||
->orderBy('batch', 'asc')
|
||||
->orderBy('migration', 'asc')
|
||||
->pluck('batch', 'migration')->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Log that a migration was run.
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $batch
|
||||
* @return void
|
||||
*/
|
||||
public function log($file, $batch)
|
||||
{
|
||||
$record = ['migration' => $file, 'batch' => $batch];
|
||||
|
||||
$this->table()->insert($record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a migration from the log.
|
||||
*
|
||||
* @param object $migration
|
||||
* @return void
|
||||
*/
|
||||
public function delete($migration)
|
||||
{
|
||||
$this->table()->where('migration', $migration->migration)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next migration batch number.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getNextBatchNumber()
|
||||
{
|
||||
return $this->getLastBatchNumber() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last migration batch number.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLastBatchNumber()
|
||||
{
|
||||
return $this->table()->max('batch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the migration repository data store.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function createRepository()
|
||||
{
|
||||
$schema = $this->getConnection()->getSchemaBuilder();
|
||||
|
||||
$schema->create($this->table, function ($table) {
|
||||
// The migrations table is responsible for keeping track of which of the
|
||||
// migrations have actually run for the application. We'll create the
|
||||
// table to hold the migration file's path as well as the batch ID.
|
||||
$table->increments('id');
|
||||
$table->string('migration');
|
||||
$table->integer('batch');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the migration repository exists.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function repositoryExists()
|
||||
{
|
||||
$schema = $this->getConnection()->getSchemaBuilder();
|
||||
|
||||
return $schema->hasTable($this->table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a query builder for the migration table.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
protected function table()
|
||||
{
|
||||
return $this->getConnection()->table($this->table)->useWritePdo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the connection resolver instance.
|
||||
*
|
||||
* @return \Illuminate\Database\ConnectionResolverInterface
|
||||
*/
|
||||
public function getConnectionResolver()
|
||||
{
|
||||
return $this->resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the database connection instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->resolver->connection($this->connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the information source to gather data.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function setSource($name)
|
||||
{
|
||||
$this->connection = $name;
|
||||
}
|
||||
}
|
30
vendor/illuminate/database/Migrations/Migration.php
vendored
Executable file
30
vendor/illuminate/database/Migrations/Migration.php
vendored
Executable file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Migrations;
|
||||
|
||||
abstract class Migration
|
||||
{
|
||||
/**
|
||||
* The name of the database connection to use.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* Enables, if supported, wrapping the migration within a transaction.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $withinTransaction = true;
|
||||
|
||||
/**
|
||||
* Get the migration connection name.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
}
|
233
vendor/illuminate/database/Migrations/MigrationCreator.php
vendored
Executable file
233
vendor/illuminate/database/Migrations/MigrationCreator.php
vendored
Executable file
@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Migrations;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class MigrationCreator
|
||||
{
|
||||
/**
|
||||
* The filesystem instance.
|
||||
*
|
||||
* @var \Illuminate\Filesystem\Filesystem
|
||||
*/
|
||||
protected $files;
|
||||
|
||||
/**
|
||||
* The custom app stubs directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $customStubPath;
|
||||
|
||||
/**
|
||||
* The registered post create hooks.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $postCreate = [];
|
||||
|
||||
/**
|
||||
* Create a new migration creator instance.
|
||||
*
|
||||
* @param \Illuminate\Filesystem\Filesystem $files
|
||||
* @param string $customStubPath
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Filesystem $files, $customStubPath)
|
||||
{
|
||||
$this->files = $files;
|
||||
$this->customStubPath = $customStubPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new migration at the given path.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
* @param string|null $table
|
||||
* @param bool $create
|
||||
* @return string
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function create($name, $path, $table = null, $create = false)
|
||||
{
|
||||
$this->ensureMigrationDoesntAlreadyExist($name, $path);
|
||||
|
||||
// First we will get the stub file for the migration, which serves as a type
|
||||
// of template for the migration. Once we have those we will populate the
|
||||
// various place-holders, save the file, and run the post create event.
|
||||
$stub = $this->getStub($table, $create);
|
||||
|
||||
$this->files->put(
|
||||
$path = $this->getPath($name, $path),
|
||||
$this->populateStub($name, $stub, $table)
|
||||
);
|
||||
|
||||
// Next, we will fire any hooks that are supposed to fire after a migration is
|
||||
// created. Once that is done we'll be ready to return the full path to the
|
||||
// migration file so it can be used however it's needed by the developer.
|
||||
$this->firePostCreateHooks($table);
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that a migration with the given name doesn't already exist.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $migrationPath
|
||||
* @return void
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function ensureMigrationDoesntAlreadyExist($name, $migrationPath = null)
|
||||
{
|
||||
if (! empty($migrationPath)) {
|
||||
$migrationFiles = $this->files->glob($migrationPath.'/*.php');
|
||||
|
||||
foreach ($migrationFiles as $migrationFile) {
|
||||
$this->files->requireOnce($migrationFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (class_exists($className = $this->getClassName($name))) {
|
||||
throw new InvalidArgumentException("A {$className} class already exists.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the migration stub file.
|
||||
*
|
||||
* @param string|null $table
|
||||
* @param bool $create
|
||||
* @return string
|
||||
*/
|
||||
protected function getStub($table, $create)
|
||||
{
|
||||
if (is_null($table)) {
|
||||
$stub = $this->files->exists($customPath = $this->customStubPath.'/migration.stub')
|
||||
? $customPath
|
||||
: $this->stubPath().'/migration.stub';
|
||||
} elseif ($create) {
|
||||
$stub = $this->files->exists($customPath = $this->customStubPath.'/migration.create.stub')
|
||||
? $customPath
|
||||
: $this->stubPath().'/migration.create.stub';
|
||||
} else {
|
||||
$stub = $this->files->exists($customPath = $this->customStubPath.'/migration.update.stub')
|
||||
? $customPath
|
||||
: $this->stubPath().'/migration.update.stub';
|
||||
}
|
||||
|
||||
return $this->files->get($stub);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the place-holders in the migration stub.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $stub
|
||||
* @param string|null $table
|
||||
* @return string
|
||||
*/
|
||||
protected function populateStub($name, $stub, $table)
|
||||
{
|
||||
$stub = str_replace(
|
||||
['DummyClass', '{{ class }}', '{{class}}'],
|
||||
$this->getClassName($name), $stub
|
||||
);
|
||||
|
||||
// Here we will replace the table place-holders with the table specified by
|
||||
// the developer, which is useful for quickly creating a tables creation
|
||||
// or update migration from the console instead of typing it manually.
|
||||
if (! is_null($table)) {
|
||||
$stub = str_replace(
|
||||
['DummyTable', '{{ table }}', '{{table}}'],
|
||||
$table, $stub
|
||||
);
|
||||
}
|
||||
|
||||
return $stub;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of a migration name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
protected function getClassName($name)
|
||||
{
|
||||
return Str::studly($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full path to the migration.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
protected function getPath($name, $path)
|
||||
{
|
||||
return $path.'/'.$this->getDatePrefix().'_'.$name.'.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire the registered post create hooks.
|
||||
*
|
||||
* @param string|null $table
|
||||
* @return void
|
||||
*/
|
||||
protected function firePostCreateHooks($table)
|
||||
{
|
||||
foreach ($this->postCreate as $callback) {
|
||||
$callback($table);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a post migration create hook.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return void
|
||||
*/
|
||||
public function afterCreate(Closure $callback)
|
||||
{
|
||||
$this->postCreate[] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the date prefix for the migration.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getDatePrefix()
|
||||
{
|
||||
return date('Y_m_d_His');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to the stubs.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function stubPath()
|
||||
{
|
||||
return __DIR__.'/stubs';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filesystem instance.
|
||||
*
|
||||
* @return \Illuminate\Filesystem\Filesystem
|
||||
*/
|
||||
public function getFilesystem()
|
||||
{
|
||||
return $this->files;
|
||||
}
|
||||
}
|
81
vendor/illuminate/database/Migrations/MigrationRepositoryInterface.php
vendored
Executable file
81
vendor/illuminate/database/Migrations/MigrationRepositoryInterface.php
vendored
Executable file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Migrations;
|
||||
|
||||
interface MigrationRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Get the completed migrations.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRan();
|
||||
|
||||
/**
|
||||
* Get list of migrations.
|
||||
*
|
||||
* @param int $steps
|
||||
* @return array
|
||||
*/
|
||||
public function getMigrations($steps);
|
||||
|
||||
/**
|
||||
* Get the last migration batch.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLast();
|
||||
|
||||
/**
|
||||
* Get the completed migrations with their batch numbers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMigrationBatches();
|
||||
|
||||
/**
|
||||
* Log that a migration was run.
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $batch
|
||||
* @return void
|
||||
*/
|
||||
public function log($file, $batch);
|
||||
|
||||
/**
|
||||
* Remove a migration from the log.
|
||||
*
|
||||
* @param object $migration
|
||||
* @return void
|
||||
*/
|
||||
public function delete($migration);
|
||||
|
||||
/**
|
||||
* Get the next migration batch number.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getNextBatchNumber();
|
||||
|
||||
/**
|
||||
* Create the migration repository data store.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function createRepository();
|
||||
|
||||
/**
|
||||
* Determine if the migration repository exists.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function repositoryExists();
|
||||
|
||||
/**
|
||||
* Set the information source to gather data.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function setSource($name);
|
||||
}
|
659
vendor/illuminate/database/Migrations/Migrator.php
vendored
Executable file
659
vendor/illuminate/database/Migrations/Migrator.php
vendored
Executable file
@ -0,0 +1,659 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Migrations;
|
||||
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Database\ConnectionResolverInterface as Resolver;
|
||||
use Illuminate\Database\Events\MigrationEnded;
|
||||
use Illuminate\Database\Events\MigrationsEnded;
|
||||
use Illuminate\Database\Events\MigrationsStarted;
|
||||
use Illuminate\Database\Events\MigrationStarted;
|
||||
use Illuminate\Database\Events\NoPendingMigrations;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class Migrator
|
||||
{
|
||||
/**
|
||||
* The event dispatcher instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Events\Dispatcher
|
||||
*/
|
||||
protected $events;
|
||||
|
||||
/**
|
||||
* The migration repository implementation.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\MigrationRepositoryInterface
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* The filesystem instance.
|
||||
*
|
||||
* @var \Illuminate\Filesystem\Filesystem
|
||||
*/
|
||||
protected $files;
|
||||
|
||||
/**
|
||||
* The connection resolver instance.
|
||||
*
|
||||
* @var \Illuminate\Database\ConnectionResolverInterface
|
||||
*/
|
||||
protected $resolver;
|
||||
|
||||
/**
|
||||
* The name of the default connection.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* The paths to all of the migration files.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $paths = [];
|
||||
|
||||
/**
|
||||
* The output interface implementation.
|
||||
*
|
||||
* @var \Symfony\Component\Console\Output\OutputInterface
|
||||
*/
|
||||
protected $output;
|
||||
|
||||
/**
|
||||
* Create a new migrator instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\MigrationRepositoryInterface $repository
|
||||
* @param \Illuminate\Database\ConnectionResolverInterface $resolver
|
||||
* @param \Illuminate\Filesystem\Filesystem $files
|
||||
* @param \Illuminate\Contracts\Events\Dispatcher|null $dispatcher
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(MigrationRepositoryInterface $repository,
|
||||
Resolver $resolver,
|
||||
Filesystem $files,
|
||||
Dispatcher $dispatcher = null)
|
||||
{
|
||||
$this->files = $files;
|
||||
$this->events = $dispatcher;
|
||||
$this->resolver = $resolver;
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the pending migrations at a given path.
|
||||
*
|
||||
* @param array|string $paths
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
public function run($paths = [], array $options = [])
|
||||
{
|
||||
// Once we grab all of the migration files for the path, we will compare them
|
||||
// against the migrations that have already been run for this package then
|
||||
// run each of the outstanding migrations against a database connection.
|
||||
$files = $this->getMigrationFiles($paths);
|
||||
|
||||
$this->requireFiles($migrations = $this->pendingMigrations(
|
||||
$files, $this->repository->getRan()
|
||||
));
|
||||
|
||||
// Once we have all these migrations that are outstanding we are ready to run
|
||||
// we will go ahead and run them "up". This will execute each migration as
|
||||
// an operation against a database. Then we'll return this list of them.
|
||||
$this->runPending($migrations, $options);
|
||||
|
||||
return $migrations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the migration files that have not yet run.
|
||||
*
|
||||
* @param array $files
|
||||
* @param array $ran
|
||||
* @return array
|
||||
*/
|
||||
protected function pendingMigrations($files, $ran)
|
||||
{
|
||||
return Collection::make($files)
|
||||
->reject(function ($file) use ($ran) {
|
||||
return in_array($this->getMigrationName($file), $ran);
|
||||
})->values()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an array of migrations.
|
||||
*
|
||||
* @param array $migrations
|
||||
* @param array $options
|
||||
* @return void
|
||||
*/
|
||||
public function runPending(array $migrations, array $options = [])
|
||||
{
|
||||
// First we will just make sure that there are any migrations to run. If there
|
||||
// aren't, we will just make a note of it to the developer so they're aware
|
||||
// that all of the migrations have been run against this database system.
|
||||
if (count($migrations) === 0) {
|
||||
$this->fireMigrationEvent(new NoPendingMigrations('up'));
|
||||
|
||||
$this->note('<info>Nothing to migrate.</info>');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Next, we will get the next batch number for the migrations so we can insert
|
||||
// correct batch number in the database migrations repository when we store
|
||||
// each migration's execution. We will also extract a few of the options.
|
||||
$batch = $this->repository->getNextBatchNumber();
|
||||
|
||||
$pretend = $options['pretend'] ?? false;
|
||||
|
||||
$step = $options['step'] ?? false;
|
||||
|
||||
$this->fireMigrationEvent(new MigrationsStarted);
|
||||
|
||||
// Once we have the array of migrations, we will spin through them and run the
|
||||
// migrations "up" so the changes are made to the databases. We'll then log
|
||||
// that the migration was run so we don't repeat it next time we execute.
|
||||
foreach ($migrations as $file) {
|
||||
$this->runUp($file, $batch, $pretend);
|
||||
|
||||
if ($step) {
|
||||
$batch++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->fireMigrationEvent(new MigrationsEnded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run "up" a migration instance.
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $batch
|
||||
* @param bool $pretend
|
||||
* @return void
|
||||
*/
|
||||
protected function runUp($file, $batch, $pretend)
|
||||
{
|
||||
// First we will resolve a "real" instance of the migration class from this
|
||||
// migration file name. Once we have the instances we can run the actual
|
||||
// command such as "up" or "down", or we can just simulate the action.
|
||||
$migration = $this->resolve(
|
||||
$name = $this->getMigrationName($file)
|
||||
);
|
||||
|
||||
if ($pretend) {
|
||||
return $this->pretendToRun($migration, 'up');
|
||||
}
|
||||
|
||||
$this->note("<comment>Migrating:</comment> {$name}");
|
||||
|
||||
$startTime = microtime(true);
|
||||
|
||||
$this->runMigration($migration, 'up');
|
||||
|
||||
$runTime = round(microtime(true) - $startTime, 2);
|
||||
|
||||
// Once we have run a migrations class, we will log that it was run in this
|
||||
// repository so that we don't try to run it next time we do a migration
|
||||
// in the application. A migration repository keeps the migrate order.
|
||||
$this->repository->log($name, $batch);
|
||||
|
||||
$this->note("<info>Migrated:</info> {$name} ({$runTime} seconds)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the last migration operation.
|
||||
*
|
||||
* @param array|string $paths
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
public function rollback($paths = [], array $options = [])
|
||||
{
|
||||
// We want to pull in the last batch of migrations that ran on the previous
|
||||
// migration operation. We'll then reverse those migrations and run each
|
||||
// of them "down" to reverse the last migration "operation" which ran.
|
||||
$migrations = $this->getMigrationsForRollback($options);
|
||||
|
||||
if (count($migrations) === 0) {
|
||||
$this->fireMigrationEvent(new NoPendingMigrations('down'));
|
||||
|
||||
$this->note('<info>Nothing to rollback.</info>');
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->rollbackMigrations($migrations, $paths, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the migrations for a rollback operation.
|
||||
*
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
protected function getMigrationsForRollback(array $options)
|
||||
{
|
||||
if (($steps = $options['step'] ?? 0) > 0) {
|
||||
return $this->repository->getMigrations($steps);
|
||||
}
|
||||
|
||||
return $this->repository->getLast();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the given migrations.
|
||||
*
|
||||
* @param array $migrations
|
||||
* @param array|string $paths
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
protected function rollbackMigrations(array $migrations, $paths, array $options)
|
||||
{
|
||||
$rolledBack = [];
|
||||
|
||||
$this->requireFiles($files = $this->getMigrationFiles($paths));
|
||||
|
||||
$this->fireMigrationEvent(new MigrationsStarted);
|
||||
|
||||
// Next we will run through all of the migrations and call the "down" method
|
||||
// which will reverse each migration in order. This getLast method on the
|
||||
// repository already returns these migration's names in reverse order.
|
||||
foreach ($migrations as $migration) {
|
||||
$migration = (object) $migration;
|
||||
|
||||
if (! $file = Arr::get($files, $migration->migration)) {
|
||||
$this->note("<fg=red>Migration not found:</> {$migration->migration}");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$rolledBack[] = $file;
|
||||
|
||||
$this->runDown(
|
||||
$file, $migration,
|
||||
$options['pretend'] ?? false
|
||||
);
|
||||
}
|
||||
|
||||
$this->fireMigrationEvent(new MigrationsEnded);
|
||||
|
||||
return $rolledBack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rolls all of the currently applied migrations back.
|
||||
*
|
||||
* @param array|string $paths
|
||||
* @param bool $pretend
|
||||
* @return array
|
||||
*/
|
||||
public function reset($paths = [], $pretend = false)
|
||||
{
|
||||
// Next, we will reverse the migration list so we can run them back in the
|
||||
// correct order for resetting this database. This will allow us to get
|
||||
// the database back into its "empty" state ready for the migrations.
|
||||
$migrations = array_reverse($this->repository->getRan());
|
||||
|
||||
if (count($migrations) === 0) {
|
||||
$this->note('<info>Nothing to rollback.</info>');
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->resetMigrations($migrations, $paths, $pretend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the given migrations.
|
||||
*
|
||||
* @param array $migrations
|
||||
* @param array $paths
|
||||
* @param bool $pretend
|
||||
* @return array
|
||||
*/
|
||||
protected function resetMigrations(array $migrations, array $paths, $pretend = false)
|
||||
{
|
||||
// Since the getRan method that retrieves the migration name just gives us the
|
||||
// migration name, we will format the names into objects with the name as a
|
||||
// property on the objects so that we can pass it to the rollback method.
|
||||
$migrations = collect($migrations)->map(function ($m) {
|
||||
return (object) ['migration' => $m];
|
||||
})->all();
|
||||
|
||||
return $this->rollbackMigrations(
|
||||
$migrations, $paths, compact('pretend')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run "down" a migration instance.
|
||||
*
|
||||
* @param string $file
|
||||
* @param object $migration
|
||||
* @param bool $pretend
|
||||
* @return void
|
||||
*/
|
||||
protected function runDown($file, $migration, $pretend)
|
||||
{
|
||||
// First we will get the file name of the migration so we can resolve out an
|
||||
// instance of the migration. Once we get an instance we can either run a
|
||||
// pretend execution of the migration or we can run the real migration.
|
||||
$instance = $this->resolve(
|
||||
$name = $this->getMigrationName($file)
|
||||
);
|
||||
|
||||
$this->note("<comment>Rolling back:</comment> {$name}");
|
||||
|
||||
if ($pretend) {
|
||||
return $this->pretendToRun($instance, 'down');
|
||||
}
|
||||
|
||||
$startTime = microtime(true);
|
||||
|
||||
$this->runMigration($instance, 'down');
|
||||
|
||||
$runTime = round(microtime(true) - $startTime, 2);
|
||||
|
||||
// Once we have successfully run the migration "down" we will remove it from
|
||||
// the migration repository so it will be considered to have not been run
|
||||
// by the application then will be able to fire by any later operation.
|
||||
$this->repository->delete($migration);
|
||||
|
||||
$this->note("<info>Rolled back:</info> {$name} ({$runTime} seconds)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a migration inside a transaction if the database supports it.
|
||||
*
|
||||
* @param object $migration
|
||||
* @param string $method
|
||||
* @return void
|
||||
*/
|
||||
protected function runMigration($migration, $method)
|
||||
{
|
||||
$connection = $this->resolveConnection(
|
||||
$migration->getConnection()
|
||||
);
|
||||
|
||||
$callback = function () use ($migration, $method) {
|
||||
if (method_exists($migration, $method)) {
|
||||
$this->fireMigrationEvent(new MigrationStarted($migration, $method));
|
||||
|
||||
$migration->{$method}();
|
||||
|
||||
$this->fireMigrationEvent(new MigrationEnded($migration, $method));
|
||||
}
|
||||
};
|
||||
|
||||
$this->getSchemaGrammar($connection)->supportsSchemaTransactions()
|
||||
&& $migration->withinTransaction
|
||||
? $connection->transaction($callback)
|
||||
: $callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretend to run the migrations.
|
||||
*
|
||||
* @param object $migration
|
||||
* @param string $method
|
||||
* @return void
|
||||
*/
|
||||
protected function pretendToRun($migration, $method)
|
||||
{
|
||||
foreach ($this->getQueries($migration, $method) as $query) {
|
||||
$name = get_class($migration);
|
||||
|
||||
$this->note("<info>{$name}:</info> {$query['query']}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the queries that would be run for a migration.
|
||||
*
|
||||
* @param object $migration
|
||||
* @param string $method
|
||||
* @return array
|
||||
*/
|
||||
protected function getQueries($migration, $method)
|
||||
{
|
||||
// Now that we have the connections we can resolve it and pretend to run the
|
||||
// queries against the database returning the array of raw SQL statements
|
||||
// that would get fired against the database system for this migration.
|
||||
$db = $this->resolveConnection(
|
||||
$migration->getConnection()
|
||||
);
|
||||
|
||||
return $db->pretend(function () use ($migration, $method) {
|
||||
if (method_exists($migration, $method)) {
|
||||
$migration->{$method}();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a migration instance from a file.
|
||||
*
|
||||
* @param string $file
|
||||
* @return object
|
||||
*/
|
||||
public function resolve($file)
|
||||
{
|
||||
$class = Str::studly(implode('_', array_slice(explode('_', $file), 4)));
|
||||
|
||||
return new $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the migration files in a given path.
|
||||
*
|
||||
* @param string|array $paths
|
||||
* @return array
|
||||
*/
|
||||
public function getMigrationFiles($paths)
|
||||
{
|
||||
return Collection::make($paths)->flatMap(function ($path) {
|
||||
return Str::endsWith($path, '.php') ? [$path] : $this->files->glob($path.'/*_*.php');
|
||||
})->filter()->values()->keyBy(function ($file) {
|
||||
return $this->getMigrationName($file);
|
||||
})->sortBy(function ($file, $key) {
|
||||
return $key;
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Require in all the migration files in a given path.
|
||||
*
|
||||
* @param array $files
|
||||
* @return void
|
||||
*/
|
||||
public function requireFiles(array $files)
|
||||
{
|
||||
foreach ($files as $file) {
|
||||
$this->files->requireOnce($file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the migration.
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
public function getMigrationName($path)
|
||||
{
|
||||
return str_replace('.php', '', basename($path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom migration path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public function path($path)
|
||||
{
|
||||
$this->paths = array_unique(array_merge($this->paths, [$path]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the custom migration paths.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function paths()
|
||||
{
|
||||
return $this->paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default connection name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given callback using the given connection as the default connection.
|
||||
*
|
||||
* @param string $name
|
||||
* @param callable $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function usingConnection($name, callable $callback)
|
||||
{
|
||||
$previousConnection = $this->resolver->getDefaultConnection();
|
||||
|
||||
$this->setConnection($name);
|
||||
|
||||
return tap($callback(), function () use ($previousConnection) {
|
||||
$this->setConnection($previousConnection);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default connection name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function setConnection($name)
|
||||
{
|
||||
if (! is_null($name)) {
|
||||
$this->resolver->setDefaultConnection($name);
|
||||
}
|
||||
|
||||
$this->repository->setSource($name);
|
||||
|
||||
$this->connection = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the database connection instance.
|
||||
*
|
||||
* @param string $connection
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public function resolveConnection($connection)
|
||||
{
|
||||
return $this->resolver->connection($connection ?: $this->connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the schema grammar out of a migration connection.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return \Illuminate\Database\Schema\Grammars\Grammar
|
||||
*/
|
||||
protected function getSchemaGrammar($connection)
|
||||
{
|
||||
if (is_null($grammar = $connection->getSchemaGrammar())) {
|
||||
$connection->useDefaultSchemaGrammar();
|
||||
|
||||
$grammar = $connection->getSchemaGrammar();
|
||||
}
|
||||
|
||||
return $grammar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the migration repository instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Migrations\MigrationRepositoryInterface
|
||||
*/
|
||||
public function getRepository()
|
||||
{
|
||||
return $this->repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the migration repository exists.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function repositoryExists()
|
||||
{
|
||||
return $this->repository->repositoryExists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file system instance.
|
||||
*
|
||||
* @return \Illuminate\Filesystem\Filesystem
|
||||
*/
|
||||
public function getFilesystem()
|
||||
{
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output implementation that should be used by the console.
|
||||
*
|
||||
* @param \Symfony\Component\Console\Output\OutputInterface $output
|
||||
* @return $this
|
||||
*/
|
||||
public function setOutput(OutputInterface $output)
|
||||
{
|
||||
$this->output = $output;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a note to the console's output.
|
||||
*
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
protected function note($message)
|
||||
{
|
||||
if ($this->output) {
|
||||
$this->output->writeln($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire the given event for the migration.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Database\Events\MigrationEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function fireMigrationEvent($event)
|
||||
{
|
||||
if ($this->events) {
|
||||
$this->events->dispatch($event);
|
||||
}
|
||||
}
|
||||
}
|
31
vendor/illuminate/database/Migrations/stubs/migration.create.stub
vendored
Executable file
31
vendor/illuminate/database/Migrations/stubs/migration.create.stub
vendored
Executable file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class {{ class }} extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('{{ table }}', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('{{ table }}');
|
||||
}
|
||||
}
|
28
vendor/illuminate/database/Migrations/stubs/migration.stub
vendored
Executable file
28
vendor/illuminate/database/Migrations/stubs/migration.stub
vendored
Executable file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class {{ class }} extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
32
vendor/illuminate/database/Migrations/stubs/migration.update.stub
vendored
Executable file
32
vendor/illuminate/database/Migrations/stubs/migration.update.stub
vendored
Executable file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class {{ class }} extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('{{ table }}', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('{{ table }}', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
}
|
66
vendor/illuminate/database/MySqlConnection.php
vendored
Executable file
66
vendor/illuminate/database/MySqlConnection.php
vendored
Executable file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Doctrine\DBAL\Driver\PDOMySql\Driver as DoctrineDriver;
|
||||
use Illuminate\Database\Query\Grammars\MySqlGrammar as QueryGrammar;
|
||||
use Illuminate\Database\Query\Processors\MySqlProcessor;
|
||||
use Illuminate\Database\Schema\Grammars\MySqlGrammar as SchemaGrammar;
|
||||
use Illuminate\Database\Schema\MySqlBuilder;
|
||||
|
||||
class MySqlConnection extends Connection
|
||||
{
|
||||
/**
|
||||
* Get the default query grammar instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Grammars\MySqlGrammar
|
||||
*/
|
||||
protected function getDefaultQueryGrammar()
|
||||
{
|
||||
return $this->withTablePrefix(new QueryGrammar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a schema builder instance for the connection.
|
||||
*
|
||||
* @return \Illuminate\Database\Schema\MySqlBuilder
|
||||
*/
|
||||
public function getSchemaBuilder()
|
||||
{
|
||||
if (is_null($this->schemaGrammar)) {
|
||||
$this->useDefaultSchemaGrammar();
|
||||
}
|
||||
|
||||
return new MySqlBuilder($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default schema grammar instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Schema\Grammars\MySqlGrammar
|
||||
*/
|
||||
protected function getDefaultSchemaGrammar()
|
||||
{
|
||||
return $this->withTablePrefix(new SchemaGrammar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default post processor instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Processors\MySqlProcessor
|
||||
*/
|
||||
protected function getDefaultPostProcessor()
|
||||
{
|
||||
return new MySqlProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Doctrine DBAL driver.
|
||||
*
|
||||
* @return \Doctrine\DBAL\Driver\PDOMySql\Driver
|
||||
*/
|
||||
protected function getDoctrineDriver()
|
||||
{
|
||||
return new DoctrineDriver;
|
||||
}
|
||||
}
|
93
vendor/illuminate/database/PostgresConnection.php
vendored
Executable file
93
vendor/illuminate/database/PostgresConnection.php
vendored
Executable file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Doctrine\DBAL\Driver\PDOPgSql\Driver as DoctrineDriver;
|
||||
use Illuminate\Database\Query\Grammars\PostgresGrammar as QueryGrammar;
|
||||
use Illuminate\Database\Query\Processors\PostgresProcessor;
|
||||
use Illuminate\Database\Schema\Grammars\PostgresGrammar as SchemaGrammar;
|
||||
use Illuminate\Database\Schema\PostgresBuilder;
|
||||
use PDO;
|
||||
|
||||
class PostgresConnection extends Connection
|
||||
{
|
||||
/**
|
||||
* Bind values to their parameters in the given statement.
|
||||
*
|
||||
* @param \PDOStatement $statement
|
||||
* @param array $bindings
|
||||
* @return void
|
||||
*/
|
||||
public function bindValues($statement, $bindings)
|
||||
{
|
||||
foreach ($bindings as $key => $value) {
|
||||
if (is_int($value)) {
|
||||
$pdoParam = PDO::PARAM_INT;
|
||||
} elseif (is_resource($value)) {
|
||||
$pdoParam = PDO::PARAM_LOB;
|
||||
} else {
|
||||
$pdoParam = PDO::PARAM_STR;
|
||||
}
|
||||
|
||||
$statement->bindValue(
|
||||
is_string($key) ? $key : $key + 1,
|
||||
$value,
|
||||
$pdoParam
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default query grammar instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Grammars\PostgresGrammar
|
||||
*/
|
||||
protected function getDefaultQueryGrammar()
|
||||
{
|
||||
return $this->withTablePrefix(new QueryGrammar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a schema builder instance for the connection.
|
||||
*
|
||||
* @return \Illuminate\Database\Schema\PostgresBuilder
|
||||
*/
|
||||
public function getSchemaBuilder()
|
||||
{
|
||||
if (is_null($this->schemaGrammar)) {
|
||||
$this->useDefaultSchemaGrammar();
|
||||
}
|
||||
|
||||
return new PostgresBuilder($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default schema grammar instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Schema\Grammars\PostgresGrammar
|
||||
*/
|
||||
protected function getDefaultSchemaGrammar()
|
||||
{
|
||||
return $this->withTablePrefix(new SchemaGrammar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default post processor instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Processors\PostgresProcessor
|
||||
*/
|
||||
protected function getDefaultPostProcessor()
|
||||
{
|
||||
return new PostgresProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Doctrine DBAL driver.
|
||||
*
|
||||
* @return \Doctrine\DBAL\Driver\PDOPgSql\Driver
|
||||
*/
|
||||
protected function getDoctrineDriver()
|
||||
{
|
||||
return new DoctrineDriver;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user