diff --git a/composer.json b/composer.json index 4e23657dd..071e19848 100755 --- a/composer.json +++ b/composer.json @@ -13,8 +13,29 @@ "php": ">=8.4.23", "d11wtq/boris": "~1.0", "filp/whoops": "~2.11", + "illuminate/bus": "^13", + "illuminate/cache": "^13", + "illuminate/collections": "^13", + "illuminate/conditionable": "^13", + "illuminate/console": "^13", + "illuminate/container": "^13", + "illuminate/contracts": "^13", + "illuminate/cookie": "^13", + "illuminate/database": "^13", + "illuminate/encryption": "^13", + "illuminate/events": "^13", + "illuminate/filesystem": "^13", + "illuminate/http": "^13", + "illuminate/macroable": "^13", + "illuminate/pagination": "^13", + "illuminate/pipeline": "^13", + "illuminate/redis": "^13", + "illuminate/reflection": "^13", + "illuminate/session": "^13", + "illuminate/support": "^13", + "illuminate/view": "^13", "ircmaxell/password-compat": "~1.0", - "laravel/serializable-closure": "^1.2", + "laravel/serializable-closure": "^2.0.10", "monolog/monolog": "^3.10", "nesbot/carbon": "^3.8.4", "opis/closure": "~3.6", @@ -38,31 +59,17 @@ }, "replace": { "illuminate/auth": "self.version", - "illuminate/cache": "self.version", "illuminate/config": "self.version", - "illuminate/console": "self.version", - "illuminate/container": "self.version", - "illuminate/cookie": "self.version", - "illuminate/database": "self.version", - "illuminate/encryption": "self.version", - "illuminate/events": "self.version", "illuminate/exception": "self.version", - "illuminate/filesystem": "self.version", "illuminate/foundation": "self.version", "illuminate/hashing": "self.version", - "illuminate/http": "self.version", "illuminate/html": "self.version", "illuminate/log": "self.version", "illuminate/mail": "self.version", - "illuminate/pagination": "self.version", "illuminate/queue": "self.version", - "illuminate/redis": "self.version", "illuminate/routing": "self.version", - "illuminate/session": "self.version", - "illuminate/support": "self.version", "illuminate/translation": "self.version", "illuminate/validation": "self.version", - "illuminate/view": "self.version", "illuminate/workbench": "self.version" }, "require-dev": { diff --git a/src/Illuminate/Auth/AuthManager.php b/src/Illuminate/Auth/AuthManager.php index 63798eb33..8e331392f 100755 --- a/src/Illuminate/Auth/AuthManager.php +++ b/src/Illuminate/Auth/AuthManager.php @@ -18,11 +18,11 @@ protected function createDriver($driver) // When using the remember me functionality of the authentication services we // will need to be set the encryption instance of the guard, which allows // secure, encrypted cookie values to get generated for those cookies. - $guard->setCookieJar($this->app['cookie']); + $guard->setCookieJar($this->container['cookie']); - $guard->setDispatcher($this->app['events']); + $guard->setDispatcher($this->container['events']); - return $guard->setRequest($this->app->refresh('request', $guard, 'setRequest')); + return $guard->setRequest($this->container->refresh('request', $guard, 'setRequest')); } /** @@ -38,7 +38,7 @@ protected function callCustomCreator($driver) if ($custom instanceof Guard) return $custom; - return new Guard($custom, $this->app['session.store']); + return new Guard($custom, $this->container['session.store']); } /** @@ -50,7 +50,7 @@ public function createDatabaseDriver() { $provider = $this->createDatabaseProvider(); - return new Guard($provider, $this->app['session.store']); + return new Guard($provider, $this->container['session.store']); } /** @@ -60,14 +60,14 @@ public function createDatabaseDriver() */ protected function createDatabaseProvider() { - $connection = $this->app['db']->connection(); + $connection = $this->container['db']->connection(); // When using the basic database user provider, we need to inject the table we // want to use, since this is not an Eloquent model we will have no way to // know without telling the provider, so we'll inject the config value. - $table = $this->app['config']['auth.table']; + $table = $this->container['config']['auth.table']; - return new DatabaseUserProvider($connection, $this->app['hash'], $table); + return new DatabaseUserProvider($connection, $this->container['hash'], $table); } /** @@ -79,7 +79,7 @@ public function createEloquentDriver() { $provider = $this->createEloquentProvider(); - return new Guard($provider, $this->app['session.store']); + return new Guard($provider, $this->container['session.store']); } /** @@ -89,9 +89,9 @@ public function createEloquentDriver() */ protected function createEloquentProvider() { - $model = $this->app['config']['auth.model']; + $model = $this->container['config']['auth.model']; - return new EloquentUserProvider($this->app['hash'], $model); + return new EloquentUserProvider($this->container['hash'], $model); } /** @@ -101,7 +101,7 @@ protected function createEloquentProvider() */ public function getDefaultDriver() { - return $this->app['config']['auth.driver']; + return $this->container['config']['auth.driver']; } /** @@ -112,7 +112,7 @@ public function getDefaultDriver() */ public function setDefaultDriver($name) { - $this->app['config']['auth.driver'] = $name; + $this->container['config']['auth.driver'] = $name; } } diff --git a/src/Illuminate/Auth/AuthServiceProvider.php b/src/Illuminate/Auth/AuthServiceProvider.php index 9a6bd7f0a..4a5c509d8 100755 --- a/src/Illuminate/Auth/AuthServiceProvider.php +++ b/src/Illuminate/Auth/AuthServiceProvider.php @@ -18,7 +18,7 @@ class AuthServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('auth', function($app) + $this->app->singleton('auth', function($app) { // Once the authentication service has actually been requested by the developer // we will set a variable in the application indicating such. This helps us diff --git a/src/Illuminate/Auth/Console/ClearRemindersCommand.php b/src/Illuminate/Auth/Console/ClearRemindersCommand.php index 8bb5cb220..3ddf69321 100644 --- a/src/Illuminate/Auth/Console/ClearRemindersCommand.php +++ b/src/Illuminate/Auth/Console/ClearRemindersCommand.php @@ -23,7 +23,7 @@ class ClearRemindersCommand extends Command { * * @return void */ - public function fire() + public function handle() { $this->laravel['auth.reminder.repository']->deleteExpired(); diff --git a/src/Illuminate/Auth/Console/RemindersControllerCommand.php b/src/Illuminate/Auth/Console/RemindersControllerCommand.php index cdc45fc44..4168738bb 100644 --- a/src/Illuminate/Auth/Console/RemindersControllerCommand.php +++ b/src/Illuminate/Auth/Console/RemindersControllerCommand.php @@ -45,7 +45,7 @@ public function __construct(Filesystem $files) * * @return void */ - public function fire() + public function handle() { $destination = $this->getPath() . '/RemindersController.php'; diff --git a/src/Illuminate/Auth/Console/RemindersTableCommand.php b/src/Illuminate/Auth/Console/RemindersTableCommand.php index c03801cbb..f0d9e8a41 100644 --- a/src/Illuminate/Auth/Console/RemindersTableCommand.php +++ b/src/Illuminate/Auth/Console/RemindersTableCommand.php @@ -44,7 +44,7 @@ public function __construct(Filesystem $files) * * @return void */ - public function fire() + public function handle() { $fullPath = $this->createBaseMigration(); diff --git a/src/Illuminate/Auth/Reminders/ReminderServiceProvider.php b/src/Illuminate/Auth/Reminders/ReminderServiceProvider.php index 0c3664023..125c0bd1a 100755 --- a/src/Illuminate/Auth/Reminders/ReminderServiceProvider.php +++ b/src/Illuminate/Auth/Reminders/ReminderServiceProvider.php @@ -36,7 +36,7 @@ public function register() */ protected function registerPasswordBroker() { - $this->app->bindShared('auth.reminder', function($app) + $this->app->singleton('auth.reminder', function($app) { // The reminder repository is responsible for storing the user e-mail addresses // and password reset tokens. It will be used to verify the tokens are valid @@ -65,7 +65,7 @@ protected function registerPasswordBroker() */ protected function registerReminderRepository() { - $this->app->bindShared('auth.reminder.repository', function($app) + $this->app->singleton('auth.reminder.repository', function($app) { $connection = $app['db']->connection(); @@ -89,17 +89,17 @@ protected function registerReminderRepository() */ protected function registerCommands() { - $this->app->bindShared('command.auth.reminders', function($app) + $this->app->singleton('command.auth.reminders', function($app) { return new RemindersTableCommand($app['files']); }); - $this->app->bindShared('command.auth.reminders.clear', function() + $this->app->singleton('command.auth.reminders.clear', function() { return new ClearRemindersCommand; }); - $this->app->bindShared('command.auth.reminders.controller', function($app) + $this->app->singleton('command.auth.reminders.controller', function($app) { return new RemindersControllerCommand($app['files']); }); diff --git a/src/Illuminate/Cache/CacheServiceProvider.php b/src/Illuminate/Cache/CacheServiceProvider.php index 4c17e24c6..0e3c611cc 100755 --- a/src/Illuminate/Cache/CacheServiceProvider.php +++ b/src/Illuminate/Cache/CacheServiceProvider.php @@ -18,17 +18,17 @@ class CacheServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('cache', function($app) + $this->app->singleton('cache', function($app) { return new CacheManager($app); }); - $this->app->bindShared('cache.store', function($app) + $this->app->singleton('cache.store', function($app) { return $app['cache']->driver(); }); - $this->app->bindShared('memcached.connector', function() + $this->app->singleton('memcached.connector', function() { return new MemcachedConnector; }); @@ -43,12 +43,12 @@ public function register() */ public function registerCommands() { - $this->app->bindShared('command.cache.clear', function($app) + $this->app->singleton('command.cache.clear', function($app) { return new Console\ClearCommand($app['cache'], $app['files']); }); - $this->app->bindShared('command.cache.table', function($app) + $this->app->singleton('command.cache.table', function($app) { return new Console\CacheTableCommand($app['files']); }); diff --git a/src/Illuminate/CachedRouting/RoutingServiceProvider.php b/src/Illuminate/CachedRouting/RoutingServiceProvider.php index eff880aae..472777e66 100644 --- a/src/Illuminate/CachedRouting/RoutingServiceProvider.php +++ b/src/Illuminate/CachedRouting/RoutingServiceProvider.php @@ -56,7 +56,7 @@ public function register() */ protected function registerRouter() { - $this->app['router'] = $this->app->share( + $this->app->singleton('router', function ($app) { $router = new Router($app['events'], $app); diff --git a/src/Illuminate/Console/Application.php b/src/Illuminate/Console/Application.php index 23cc4cd0c..a0cd590f7 100755 --- a/src/Illuminate/Console/Application.php +++ b/src/Illuminate/Console/Application.php @@ -22,6 +22,27 @@ class Application extends \Symfony\Component\Console\Application { */ protected $laravel; + /** + * Callbacks to run when a console application is starting. + * + * ponytail: BC shim for v13 Support\ServiceProvider::commands(), which calls + * Illuminate\Console\Application::starting(). Remove when console swaps to v13 (task 4.2/4.3). + * + * @var callable[] + */ + protected static $startingCallbacks = array(); + + /** + * Register a callback to run when the console application is starting. + * + * @param callable $callback + * @return void + */ + public static function starting($callback) + { + static::$startingCallbacks[] = $callback; + } + /** * Create and boot a new Console application. * @@ -51,6 +72,11 @@ public static function make($app) $app->instance('artisan', $console); + foreach (static::$startingCallbacks as $callback) + { + $callback($console); + } + return $console; } @@ -153,7 +179,19 @@ public function resolveCommands($commands) foreach ($commands as $command) { - $this->resolve($command); + try + { + $this->resolve($command); + } + catch (\Throwable $e) + { + // ponytail: some v13 components (session/cache/…) register console commands + // that extend v13 console base classes absent from the not-yet-swapped fork + // console. Skip the ones that can't load so artisan still boots; they return + // with the console swap (task 4.2). Commands that load fine still register. + error_log('[l13] skipped unresolvable console command ' + . (is_string($command) ? $command : gettype($command)) . ': ' . $e->getMessage()); + } } } diff --git a/src/Illuminate/Console/Command.php b/src/Illuminate/Console/Command.php index c81337b43..3809075c0 100755 --- a/src/Illuminate/Console/Command.php +++ b/src/Illuminate/Console/Command.php @@ -63,6 +63,19 @@ public function __construct() $this->specifyParameters(); } + /** + * ponytail: BC shim — exists so v13 component commands that declare + * `#[\Override] configureDefaults()` (against the v13 console Command) can load under + * the not-yet-swapped fork console. The fork configures via the constructor / + * specifyParameters() instead, so this is a no-op. Remove at the console swap (task 4.2). + * + * @return void + */ + protected function configureDefaults() + { + // + } + /** * Specify the arguments and options on the command. * diff --git a/src/Illuminate/Console/MigrationGeneratorCommand.php b/src/Illuminate/Console/MigrationGeneratorCommand.php new file mode 100644 index 000000000..187c11863 --- /dev/null +++ b/src/Illuminate/Console/MigrationGeneratorCommand.php @@ -0,0 +1,39 @@ +error('make:*-table generators require the v13 console (L13 migration task 4.2).'); + } + + return 1; + } +} diff --git a/src/Illuminate/Console/Prohibitable.php b/src/Illuminate/Console/Prohibitable.php new file mode 100644 index 000000000..e706dbe6e --- /dev/null +++ b/src/Illuminate/Console/Prohibitable.php @@ -0,0 +1,45 @@ +components->error('This command is prohibited from running in this environment.'); + } + + return true; + } +} diff --git a/src/Illuminate/Container/BindingResolutionException.php b/src/Illuminate/Container/BindingResolutionException.php deleted file mode 100644 index 36975df20..000000000 --- a/src/Illuminate/Container/BindingResolutionException.php +++ /dev/null @@ -1,3 +0,0 @@ -make($segments[0]), $method], $parameters - ); - } - - /** - * Call a method that has been bound to the container. - * - * @param Container $container - * @param callable|string $callback - * @param mixed $default - * - * @return mixed - */ - protected static function callBoundMethod(Container $container, callable|string $callback, $default) - { - if (! is_array($callback)) { - return Util::unwrapIfClosure($default); - } - - // Here we need to turn the array callable into a Class@method string we can use to - // examine the container and see if there are any method bindings for this given - // method. If there are, we can call this method binding callback immediately. - $method = static::normalizeMethod($callback); - - if ($container->hasMethodBinding($method)) { - return $container->callMethodBinding($method, $callback[0]); - } - - // Diqo: - // This is where the array callback is executed. Note that the - // value that is used for execution is only $default, which is - // the closure that should haved "closure" in the callback and the - // required parameters. - // - // To further understand the mechanisme, see `call` on how it contrstruct - // the closure before calling this `callBoundMethod`. - // - // So, unwrapIfClosure just executed the $default closure. - return Util::unwrapIfClosure($default); - } - - /** - * Normalize the given callback into a Class@method string. - * - * @param callable $callback - * @return string - */ - protected static function normalizeMethod(callable $callback): string - { - $class = is_string($callback[0]) ? $callback[0] : get_class($callback[0]); - - return "{$class}@{$callback[1]}"; - } - - /** - * Get all dependencies for a given method. - * - * @param Container $container - * @param callable|string $callback - * @param array $parameters - * - * @return array - * - * @throws BindingResolutionException - * @throws ReflectionException - */ - protected static function getMethodDependencies( - Container $container, - callable|string $callback, - array $parameters = [] - ): array { - $dependencies = []; - - foreach (static::getCallReflector($callback)->getParameters() as $parameter) { - static::addDependencyForCallParameter($container, $parameter, $parameters, $dependencies); - } - - return array_merge($dependencies, array_values($parameters)); - } - - /** - * Get the proper reflection instance for the given callback. - * - * @param callable|string $callback - * @return \ReflectionFunctionAbstract - * - * @throws ReflectionException - */ - protected static function getCallReflector(callable|string $callback) - { - if (is_string($callback) && str_contains($callback, '::')) { - $callback = explode('::', $callback); - } elseif (is_object($callback) && ! $callback instanceof Closure) { - $callback = [$callback, '__invoke']; - } - - return is_array($callback) - ? new ReflectionMethod($callback[0], $callback[1]) - : new ReflectionFunction($callback); - } - - /** - * Get the dependency for the given call parameter. - * - * @param Container $container - * @param ReflectionParameter $parameter - * @param array $parameters - * @param array $dependencies - * - * @return void - * - * @throws BindingResolutionException - * @throws ReflectionException - */ - protected static function addDependencyForCallParameter( - Container $container, - ReflectionParameter $parameter, - array &$parameters, - array &$dependencies - ): void { - if (array_key_exists($paramName = $parameter->getName(), $parameters)) { - $dependencies[] = $parameters[$paramName]; - - unset($parameters[$paramName]); - } elseif (! is_null($className = Reflector::getParameterClassName($parameter))) { - if (array_key_exists($className, $parameters)) { - $dependencies[] = $parameters[$className]; - - unset($parameters[$className]); - } elseif ($parameter->isVariadic()) { - $variadicDependencies = $container->make($className); - - $dependencies = array_merge($dependencies, is_array($variadicDependencies) - ? $variadicDependencies - : [$variadicDependencies]); - } else { - $dependencies[] = $container->make($className); - } - } elseif ($parameter->isDefaultValueAvailable()) { - $dependencies[] = $parameter->getDefaultValue(); - } elseif (! $parameter->isOptional() && ! array_key_exists($paramName, $parameters)) { - $message = "Unable to resolve dependency [{$parameter}] in class {$parameter->getDeclaringClass()->getName()}"; - - throw new BindingResolutionException($message); - } - } - - /** - * Determine if the given string is in Class@method syntax. - * - * @param mixed $callback - * @return bool - */ - protected static function isCallableWithAtSign($callback): bool - { - return is_string($callback) && str_contains($callback, '@'); - } -} diff --git a/src/Illuminate/Container/CircularDependencyException.php b/src/Illuminate/Container/CircularDependencyException.php deleted file mode 100644 index 9b00b3301..000000000 --- a/src/Illuminate/Container/CircularDependencyException.php +++ /dev/null @@ -1,10 +0,0 @@ -getAlias($c); - } - - return new ContextualBindingBuilder($this, $aliases); - } - - /** - * Add a contextual binding to the container. - * - * @param string $concrete - * @param string $abstract - * @param \Closure|string $implementation - * - * @return void - */ - public function addContextualBinding($concrete, $abstract, $implementation): void - { - $this->contextual[$concrete][$this->getAlias($abstract)] = $implementation; - } - - /** - * Determine if the given abstract type has been bound. - * - * @param string $abstract - * @return bool - */ - public function bound($abstract): bool - { - return isset($this->bindings[$abstract]) || - isset($this->instances[$abstract]) || - $this->isAlias($abstract); - } - - /** - * Determine if the container has a method binding. - * - * @param string $method - * @return bool - */ - public function hasMethodBinding($method): bool - { - return isset($this->methodBindings[$method]); - } - - /** - * Bind a callback to resolve with Container::call. - * - * @param array|string $method - * @param \Closure $callback - * @return void - */ - public function bindMethod($method, $callback): void - { - $this->methodBindings[$this->parseBindMethod($method)] = $callback; - } - - /** - * Get the method to be bound in class@method format. - * - * @param array|string $method - * @return string - */ - protected function parseBindMethod($method): string - { - if (is_array($method)) { - return $method[0].'@'.$method[1]; - } - - return $method; - } - - /** - * Get the method binding for the given method. - * - * @param string $method - * @param mixed $instance - * @return mixed - */ - public function callMethodBinding($method, $instance) - { - return call_user_func($this->methodBindings[$method], $instance, $this); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function has(string $id): bool - { - return $this->bound($id); - } - - /** - * Determine if the given abstract type has been resolved. - * - * @param string $abstract - * @return bool - */ - public function resolved($abstract): bool - { - if ($this->isAlias($abstract)) { - $abstract = $this->getAlias($abstract); - } - - return isset($this->resolved[$abstract]) || isset($this->instances[$abstract]); - } - - /** - * Determine if a given string is an alias. - * - * @param string $name - * @return bool - */ - public function isAlias($name): bool - { - return isset($this->aliases[$name]); - } - - /** - * Register a binding with the container. - * - * @param string|array $abstract - * @param $concrete - * @param bool $shared - * - * @return void - * @throws BindingResolutionException - * @throws ReflectionException - */ - public function bind($abstract, $concrete = null, $shared = false): void - { - // If the given types are actually an array, we will assume an alias is being - // defined and will grab this "real" abstract class name and register this - // alias with the container so that it can be used as a shortcut for it. - if (is_array($abstract)) { - [$abstract, $alias] = $this->extractAlias($abstract); - - $this->alias($abstract, $alias); - } - - $this->dropStaleInstances($abstract); - - // If no concrete type was given, we will simply set the concrete type to the - // abstract type. This will allow concrete type to be registered as shared - // without being forced to state their classes in both of the parameter. - if (is_null($concrete)) { - $concrete = $abstract; - } - - // If the factory is not a Closure, it means it is just a class name which is - // is bound into this container to the abstract type and we will just wrap - // it up inside a Closure to make things more convenient when extending. - if ( ! $concrete instanceof Closure) { - if (! is_string($concrete)) { - throw new \TypeError(self::class.'::bind(): Argument #2 ($concrete) must be of type Closure|string|null'); - } - - $concrete = $this->getClosure($abstract, $concrete); - } - - $this->bindings[$abstract] = compact('concrete', 'shared'); - - // If the abstract type was already resolved in this container we'll fire the - // rebound listener so that any objects which have already gotten resolved - // can have their copy of the object updated via the listener callbacks. - if ($this->resolved($abstract)) - { - $this->rebound($abstract); - } - } - - /** - * Get the Closure to be used when building a type. - * - * @param string $abstract - * @param string $concrete - * - * @return \Closure - */ - protected function getClosure(string $abstract, string $concrete): Closure - { - return function($c, $parameters = array()) use ($abstract, $concrete) { - $method = ($abstract === $concrete) ? 'build' : 'make'; - - return $c->$method($concrete, $parameters, false); - }; - } - - /** - * Register a binding if it hasn't already been registered. - * - * @param string $abstract - * @param \Closure|string|null $concrete - * @param bool $shared - * @return void - */ - public function bindIf($abstract, $concrete = null, $shared = false): void - { - if ( ! $this->bound($abstract)) { - $this->bind($abstract, $concrete, $shared); - } - } - - /** - * Register a shared binding in the container. - * - * @param string $abstract - * @param null $concrete - * - * @return void - * @throws BindingResolutionException - * @throws ReflectionException - */ - public function singleton($abstract, $concrete = null): void - { - $this->bind($abstract, $concrete, true); - } - - /** - * Register a shared binding if it hasn't already been registered. - * - * @param string $abstract - * @param \Closure|string|null $concrete - * @return void - */ - public function singletonIf($abstract, $concrete = null): void - { - if (! $this->bound($abstract)) { - $this->singleton($abstract, $concrete); - } - } - - /** - * Wrap a Closure such that it is shared. - * - * @param \Closure $closure - * @return \Closure - */ - public function share(Closure $closure): Closure - { - return function($container) use ($closure) - { - // We'll simply declare a static variable within the Closures and if it has - // not been set we will execute the given Closures to resolve this value - // and return it back to these consumers of the method as an instance. - static $object; - - if (is_null($object)) - { - $object = $closure($container); - } - - return $object; - }; - } - - /** - * Bind a shared Closure into the container. - * - * @param string $abstract - * @param \Closure $closure - * @return void - */ - public function bindShared($abstract, Closure $closure): void - { - $this->bind($abstract, $this->share($closure), true); - } - - /** - * "Extend" an abstract type in the container. - * - * @param string $abstract - * @param \Closure $closure - * - * @return void - * - * @throws BindingResolutionException - * @throws ReflectionException - */ - public function extend($abstract, Closure $closure): void - { - $abstract = $this->getAlias($abstract); - - if (isset($this->instances[$abstract])) { - $this->instances[$abstract] = $closure($this->instances[$abstract], $this); - - $this->rebound($abstract); - } else { - $this->extenders[$abstract][] = $closure; - - if ($this->resolved($abstract)) { - $this->rebound($abstract); - } - } - } - - /** - * Get an extender Closure for resolving a type. - * - * @deprecated - * @param string $abstract - * @param \Closure $closure - * @return \Closure - */ - protected function getExtender($abstract, Closure $closure): Closure - { - // To "extend" a binding, we will grab the old "resolver" Closure and pass it - // into a new one. The old resolver will be called first and the result is - // handed off to the "new" resolver, along with this container instance. - $resolver = $this->bindings[$abstract]['concrete']; - - return function($container) use ($resolver, $closure) - { - return $closure($resolver($container), $container); - }; - } - - /** - * Register an existing instance as shared in the container. - * - * @param string|array $abstract - * @param mixed $instance - * - * @throws BindingResolutionException - * @throws ReflectionException - */ - public function instance($abstract, $instance) - { - // First, we will extract the alias from the abstract if it is an array so we - // are using the correct name when binding the type. If we get an alias it - // will be registered with the container so we can resolve it out later. - if (is_array($abstract)) - { - [$abstract, $alias] = $this->extractAlias($abstract); - - $this->alias($abstract, $alias); - } - - $this->removeAbstractAlias($abstract); - - unset($this->aliases[$abstract]); - - // We'll check to determine if this type has been bound before, and if it has - // we will fire the rebound callbacks registered with the container and it - // can be updated with consuming classes that have gotten resolved here. - $isBound = $this->bound($abstract); - - $this->instances[$abstract] = $instance; - - if ($isBound) { - $this->rebound($abstract); - } - - return $instance; - } - - /** - * Remove an alias from the contextual binding alias cache. - * - * @param string $searched - * @return void - */ - protected function removeAbstractAlias($searched): void - { - if (! isset($this->aliases[$searched])) { - return; - } - - foreach ($this->abstractAliases as $abstract => $aliases) { - foreach ($aliases as $index => $alias) { - if ($alias == $searched) { - unset($this->abstractAliases[$abstract][$index]); - } - } - } - } - - /** - * Assign a set of tags to a given binding. - * - * @param array|string $abstracts - * @param array|mixed ...$tags - * @return void - */ - public function tag($abstracts, $tags): void - { - $tags = is_array($tags) ? $tags : array_slice(func_get_args(), 1); - - foreach ($tags as $tag) { - if (! isset($this->tags[$tag])) { - $this->tags[$tag] = []; - } - - foreach ((array) $abstracts as $abstract) { - $this->tags[$tag][] = $abstract; - } - } - } - - /** - * Resolve all of the bindings for a given tag. - * - * @param string $tag - */ - public function tagged($tag) - { - if (! isset($this->tags[$tag])) { - return []; - } - - return new RewindableGenerator(function () use ($tag) { - foreach ($this->tags[$tag] as $abstract) { - yield $this->make($abstract); - } - }, count($this->tags[$tag])); - } - - /** - * Alias a type to a shorter name. - * - * @param string $abstract - * @param string $alias - * @return void - */ - public function alias($abstract, $alias): void - { - if ($alias === $abstract) { - throw new LogicException("[{$abstract}] is aliased to itself."); - } - - $this->aliases[$alias] = $abstract; - - $this->abstractAliases[$abstract][] = $alias; - } - - /** - * Extract the type and alias from a given definition. - * - * @param array $definition - * @return array - */ - protected function extractAlias(array $definition): array - { - return array(key($definition), current($definition)); - } - - /** - * Bind a new callback to an abstract's rebind event. - * - * @param string $abstract - * @param \Closure $callback - * - * @return mixed - * @throws BindingResolutionException - * @throws ReflectionException - */ - public function rebinding($abstract, Closure $callback) - { - $this->reboundCallbacks[$abstract][] = $callback; - - if ($this->bound($abstract)) { - return $this->make($abstract); - } - } - - /** - * Refresh an instance on the given target and method. - * - * @param string $abstract - * @param mixed $target - * @param string $method - * - * @return mixed - * @throws BindingResolutionException - * @throws ReflectionException - */ - public function refresh($abstract, $target, $method) - { - return $this->rebinding($abstract, function($app, $instance) use ($target, $method) - { - $target->{$method}($instance); - }); - } - - /** - * Fire the "rebound" callbacks for the given abstract type. - * - * @param string $abstract - * - * @return void - * @throws BindingResolutionException - * @throws ReflectionException - */ - protected function rebound($abstract): void - { - $instance = $this->make($abstract); - - foreach ($this->getReboundCallbacks($abstract) as $callback) { - $callback($this, $instance); - } - } - - /** - * Get the rebound callbacks for a given type. - * - * @param string $abstract - * @return array - */ - protected function getReboundCallbacks($abstract): array - { - if (isset($this->reboundCallbacks[$abstract])) - { - return $this->reboundCallbacks[$abstract]; - } - - return array(); - } - - /** - * Wrap the given closure such that its dependencies will be injected when executed. - * - * @param \Closure $callback - * @param array $parameters - * @return \Closure - */ - public function wrap(Closure $callback, array $parameters = []): Closure - { - return function () use ($callback, $parameters) { - return $this->call($callback, $parameters); - }; - } - - /** - * Call the given Closure / class@method and inject its dependencies. - * - * @param callable|string $callback - * @param array $parameters - * @param null $defaultMethod - * - * @return mixed - * - * @throws BindingResolutionException - * @throws ReflectionException - */ - public function call($callback, array $parameters = [], $defaultMethod = null) - { - return BoundMethod::call($this, $callback, $parameters, $defaultMethod); - } - - /** - * Get a closure to resolve the given type from the container. - * - * @param string $abstract - * - * @return \Closure - */ - public function factory($abstract): Closure - { - return function () use ($abstract) { - return $this->make($abstract); - }; - } - - /** - * An alias function name for make(). - * - * @param string|callable $abstract - * @param array $parameters - * - * @return mixed - * - * @throws BindingResolutionException - * @throws ReflectionException - */ - public function makeWith($abstract, array $parameters = []) - { - return $this->make($abstract, $parameters); - } - - /** - * {@inheritdoc} - * - * @param string $id - * - * @return mixed - * @throws CircularDependencyException - * @throws EntryNotFoundException - */ - public function get(string $id) - { - try { - return $this->make($id); - } catch (Exception $e) { - if ($this->has($id) || $e instanceof CircularDependencyException) { - throw $e; - } - - throw new EntryNotFoundException($id, is_int($e->getCode()) ? $e->getCode() : 0, $e); - } - } - - /** - * Resolve the given type from the container. - * - * @param string|callable $abstract - * @param array $parameters - * @param bool $raiseEvents - * - * @return mixed - * @throws BindingResolutionException - * @throws \ReflectionException - */ - public function make($abstract, $parameters = array(), $raiseEvents = true) - { - $abstract = $this->getAlias($abstract); - - // First we'll fire any event handlers which handle the "before" resolving of - // specific types. This gives some hooks the chance to add various extends - // calls to change the resolution of objects that they're interested in. - if ($raiseEvents) { - $this->fireBeforeResolvingCallbacks($abstract, $parameters); - } - - $concrete = $this->getContextualConcrete($abstract); - - $needsContextualBuild = ! empty($parameters) || ! is_null($concrete); - - // If an instance of the type is currently being managed as a singleton we'll - // just return an existing instance instead of instantiating new instances - // so the developer can keep using the same objects instance every time. - if (isset($this->instances[$abstract]) && ! $needsContextualBuild) { - return $this->instances[$abstract]; - } - - if (is_null($concrete)) { - $concrete = $this->getConcrete($abstract); - } - - // We're ready to instantiate an instance of the concrete type registered for - // the binding. This will instantiate the types, as well as resolve any of - // its "nested" dependencies recursively until all have gotten resolved. - if ($this->isBuildable($concrete, $abstract)) { - $object = $this->build($concrete, $parameters); - } else { - $object = $this->make($concrete, $parameters); - } - - // If we defined any extenders for this type, we'll need to spin through them - // and apply them to the object being built. This allows for the extension - // of services, such as changing configuration or decorating the object. - foreach ($this->getExtenders($abstract) as $extender) { - $object = $extender($object, $this); - } - - // If the requested type is registered as a singleton we'll want to cache off - // the instances in "memory" so we can return it later without creating an - // entirely new instance of an object on each subsequent request for it. - if ($this->isShared($abstract) && ! $needsContextualBuild) { - $this->instances[$abstract] = $object; - } - - if ($raiseEvents) { - $this->fireResolvingCallbacks($abstract, $object); - } - - // Before returning, we will also set the resolved flag to "true". - // After that we will be ready to return back the fully constructed class instance. - $this->resolved[$abstract] = true; - - return $object; - } - - /** - * Get the contextual concrete binding for the given abstract. - * - * @param string|callable $abstract - * @return \Closure|string|array|null - */ - protected function getContextualConcrete($abstract) - { - if (! is_null($binding = $this->findInContextualBindings($abstract))) { - return $binding; - } - - // Next we need to see if a contextual binding might be bound under an alias of the - // given abstract type. So, we will need to check if any aliases exist with this - // type and then spin through them and check for contextual bindings on these. - if (empty($this->abstractAliases[$abstract])) { - return null; - } - - foreach ($this->abstractAliases[$abstract] as $alias) { - if (! is_null($binding = $this->findInContextualBindings($alias))) { - return $binding; - } - } - - return null; - } - - /** - * Find the concrete binding for the given abstract in the contextual binding array. - * - * @param string|callable $abstract - * @return \Closure|string|null - */ - protected function findInContextualBindings($abstract) - { - return $this->contextual[end($this->buildStack)][$abstract] ?? null; - } - - /** - * Get the extender callbacks for a given type. - * - * @param string $abstract - * @return array - */ - protected function getExtenders($abstract): array - { - return $this->extenders[$this->getAlias($abstract)] ?? []; - } - - /** - * Remove all of the extender callbacks for a given type. - * - * @param string $abstract - * @return void - */ - public function forgetExtenders($abstract): void - { - unset($this->extenders[$this->getAlias($abstract)]); - } - - /** - * Get the concrete type for a given abstract. - * - * @param string $abstract - * - * @return mixed $concrete - */ - protected function getConcrete(string $abstract) - { - // If we don't have a registered resolver or concrete for the type, we'll just - // assume each type is a concrete name and will attempt to resolve it as is - // since the container should be able to resolve concretes automatically. - if ( ! isset($this->bindings[$abstract])) - { - if ($this->missingLeadingSlash($abstract) && isset($this->bindings['\\'.$abstract])) - { - $abstract = '\\'.$abstract; - } - - return $abstract; - } - - return $this->bindings[$abstract]['concrete']; - } - - /** - * Determine if the given abstract has a leading slash. - * - * @param string $abstract - * - * @return bool - */ - protected function missingLeadingSlash(string $abstract): bool - { - return is_string($abstract) && strpos($abstract, '\\') !== 0; - } - - /** - * Instantiate a concrete instance of the given type. - * - * @param string|Closure $concrete - * @param array $parameters - * - * @return mixed - * - * @throws BindingResolutionException - * @throws \ReflectionException - */ - public function build($concrete, $parameters = array()) - { - // If the concrete type is actually a Closure, we will just execute it and - // hand back the results of the functions, which allows functions to be - // used as resolvers for more fine-tuned resolution of these objects. - if ($concrete instanceof Closure) { - return $concrete($this, $parameters); - } - - try { - $reflector = new ReflectionClass($concrete); - } catch (ReflectionException $e) { - throw new BindingResolutionException("Target class [$concrete] does not exist.", 0, $e); - } - - // If the type is not instantiable, the developer is attempting to resolve - // an abstract type such as an Interface of Abstract Class and there is - // no binding registered for the abstractions so we need to bail out. - if ( ! $reflector->isInstantiable()) { - $this->notInstantiable($concrete); - } - - // Diqo: - // Why do we need to hold build stack? - // This is to suport variadic binding resolution. Please check - // \Illuminate\Container\Container::resolveVariadicClass - // - // The $concrete will be popped after it has been built or the container - // faced error in building it. - $this->buildStack[] = $concrete; - - $constructor = $reflector->getConstructor(); - - // If there are no constructors, that means there are no dependencies then - // we can just resolve the instances of the objects right away, without - // resolving any other types or dependencies out of these containers. - if (is_null($constructor)) { - array_pop($this->buildStack); - - return new $concrete; - } - - try { - $dependencies = $constructor->getParameters(); - - // Once we have all the constructor's parameters we can create each of the - // dependency instances and then use the reflection instances to make a - // new instance of this class, injecting the created dependencies in. - - $parameters = $this->keyParametersByArgument( - $dependencies, $parameters - ); - - $instances = $this->getDependencies( - $dependencies, $parameters - ); - } catch (BindingResolutionException $exception) { - array_pop($this->buildStack); - - throw $exception; - } - - array_pop($this->buildStack); - - return $reflector->newInstanceArgs($instances); - } - - /** - * Throw an exception that the concrete is not instantiable. - * - * @param string $concrete - * @return void - * - * @throws BindingResolutionException - */ - protected function notInstantiable($concrete): void - { - if (! empty($this->buildStack)) { - $previous = implode(', ', $this->buildStack); - - $message = "Target [$concrete] is not instantiable while building [$previous]."; - } else { - $message = "Target [$concrete] is not instantiable."; - } - - throw new BindingResolutionException($message); - } - - /** - * Resolve all of the dependencies from the ReflectionParameters. - * - * @param array $parameters - * @param array $primitives - * - * @return array - * @throws BindingResolutionException - * @throws ReflectionException - */ - protected function getDependencies(array $parameters, array $primitives = array()): array - { - $dependencies = []; - - foreach ($parameters as $parameter) - { - $dependency = Reflector::getParameterClassName($parameter); - - if (array_key_exists($parameter->name, $primitives)) { - // If the dependency has an override for this particular build we will use - // that instead as the value. Otherwise, we will continue with this run - // of resolutions and let reflection attempt to determine the result. - $dependencies[] = $primitives[$parameter->name]; - continue; - } - - if (is_null($dependency)) { - // If the class is null, it means the dependency is a string or some other - // primitive type which we can not resolve since it is not a class and - // we will just bomb out with an error since we have no-where to go. - $result = $this->resolveNonClass($parameter); - } else { - $result = $this->resolveClass($parameter); - } - - if ($parameter->isVariadic()) { - $dependencies = array_merge($dependencies, $result); - } else { - $dependencies[] = $result; - } - } - - return $dependencies; - } - - /** - * Resolve a non-class hinted dependency. - * - * @param \ReflectionParameter $parameter - * @return mixed - * - * @throws BindingResolutionException - */ - protected function resolveNonClass(ReflectionParameter $parameter) - { - if (!is_null($concrete = $this->getContextualConcrete('$' . $parameter->getName()))) { - return Util::unwrapIfClosure($concrete, $this); - } - - if ($parameter->isDefaultValueAvailable()) { - return $parameter->getDefaultValue(); - } - - $message = "Unresolvable dependency resolving [$parameter] in class {$parameter->getDeclaringClass()->getName()}"; - - throw new BindingResolutionException($message); - } - - /** - * Resolve a class based dependency from the container. - * - * @param \ReflectionParameter $parameter - * - * @return mixed - * - * @throws BindingResolutionException - * @throws ReflectionException - */ - protected function resolveClass(ReflectionParameter $parameter) - { - try { - return $parameter->isVariadic() - ? $this->resolveVariadicClass($parameter) - : $this->make(Reflector::getParameterClassName($parameter)); - } - - // If we can not resolve the class instance, we will check to see if the value - // is optional, and if it is we will return the optional parameter value as - // the value of the dependency, similarly to how we do this with scalars. - catch (BindingResolutionException $e) - { - if ($parameter->isDefaultValueAvailable()) - { - return $parameter->getDefaultValue(); - } - - if ($parameter->isVariadic()) { - return []; - } - - throw $e; - } - } - - /** - * Resolve a class based variadic dependency from the container. - * - * @param \ReflectionParameter $parameter - * - * @return mixed - * @throws BindingResolutionException - * @throws ReflectionException - */ - protected function resolveVariadicClass(ReflectionParameter $parameter) - { - $className = Reflector::getParameterClassName($parameter); - - $abstract = $this->getAlias($className); - - if (!is_array($concrete = $this->getContextualConcrete($abstract))) { - return $this->make($className); - } - - return array_map(function ($abstract) { - return $this->make($abstract); - }, $concrete); - } - - /** - * If extra parameters are passed by numeric ID, rekey them by argument name. - * - * @param array $dependencies - * @param array $parameters - * @return array - */ - protected function keyParametersByArgument(array $dependencies, array $parameters): array - { - foreach ($parameters as $key => $value) - { - if (is_numeric($key)) - { - unset($parameters[$key]); - - $parameters[$dependencies[$key]->name] = $value; - } - } - - return $parameters; - } - - /** - * Register a new before resolving callback for all types. - * - * @param \Closure|string $abstract - * @param \Closure|null $callback - * @return void - */ - public function beforeResolving($abstract, ?Closure $callback = null) - { - if (is_string($abstract)) { - $abstract = $this->getAlias($abstract); - } - - if ($abstract instanceof Closure && is_null($callback)) { - $this->globalBeforeResolvingCallbacks[] = $abstract; - } else { - $this->beforeResolvingCallbacks[$abstract][] = $callback; - } - } - - /** - * Register a new resolving callback. - * - * @param string|callable $abstract - * @param \Closure $callback - * @return void - */ - public function resolving($abstract, ?Closure $callback = null): void - { - if (is_string($abstract)) { - $abstract = $this->getAlias($abstract); - } - - if (is_null($callback) && $abstract instanceof Closure) { - // This is global callback, where it will be called - // when the container resolves any type - $this->globalResolvingCallbacks[] = $abstract; - } else { - // Call the callback when the container resolves $abstract - $this->resolvingCallbacks[$abstract][] = $callback; - } - } - - /** - * Register a new after resolving callback for all types. - * - * @param \Closure|string $abstract - * @param \Closure|null $callback - * @return void - */ - public function afterResolving($abstract, ?Closure $callback = null) - { - if (is_string($abstract)) { - $abstract = $this->getAlias($abstract); - } - - if ($abstract instanceof Closure && is_null($callback)) { - $this->globalAfterResolvingCallbacks[] = $abstract; - } else { - $this->afterResolvingCallbacks[$abstract][] = $callback; - } - } - - /** - * Register a new resolving callback for all types. - * - * @param \Closure $callback - * @return void - */ - public function resolvingAny(Closure $callback): void - { - $this->globalResolvingCallbacks[] = $callback; - } - - /** - * Fire all of the before resolving callbacks. - * - * @param string $abstract - * @param array $parameters - * @return void - */ - protected function fireBeforeResolvingCallbacks($abstract, $parameters = []): void - { - $this->fireBeforeCallbackArray($abstract, $parameters, $this->globalBeforeResolvingCallbacks); - - foreach ($this->beforeResolvingCallbacks as $type => $callbacks) { - if ($type === $abstract || is_subclass_of($abstract, $type)) { - $this->fireBeforeCallbackArray($abstract, $parameters, $callbacks); - } - } - } - - /** - * Fire an array of callbacks with an object. - * - * @param string $abstract - * @param array $parameters - * @param array $callbacks - * @return void - */ - protected function fireBeforeCallbackArray($abstract, $parameters, array $callbacks): void - { - foreach ($callbacks as $callback) { - $callback($abstract, $parameters, $this); - } - } - - /** - * Fire all of the resolving callbacks. - * - * @param string $abstract - * @param mixed $object - * @return void - */ - protected function fireResolvingCallbacks($abstract, $object): void - { - $this->fireCallbackArray($object, $this->globalResolvingCallbacks); - - $this->fireCallbackArray( - $object, $this->getCallbacksForType($abstract, $object, $this->resolvingCallbacks) - ); - - $this->fireAfterResolvingCallbacks($abstract, $object); - } - - /** - * Fire all of the after resolving callbacks. - * - * @param string $abstract - * @param mixed $object - * @return void - */ - protected function fireAfterResolvingCallbacks($abstract, $object): void - { - $this->fireCallbackArray($object, $this->globalAfterResolvingCallbacks); - - $this->fireCallbackArray( - $object, $this->getCallbacksForType($abstract, $object, $this->afterResolvingCallbacks) - ); - } - - /** - * Get all callbacks for a given type. - * - * @param string $abstract - * @param object $object - * @param array $callbacksPerType - * @return array - */ - protected function getCallbacksForType($abstract, $object, array $callbacksPerType): array - { - $results = []; - - foreach ($callbacksPerType as $type => $callbacks) { - if ($type === $abstract || $object instanceof $type) { - $results = array_merge($results, $callbacks); - } - } - - return $results; - } - - /** - * Fire an array of callbacks with an object. - * - * @param mixed $object - * @param array $callbacks - */ - protected function fireCallbackArray($object, array $callbacks): void - { - foreach ($callbacks as $callback) { - $callback($object, $this); - } - } - - /** - * Determine if a given type is shared. - * - * @param string $abstract - * - * @return bool - */ - public function isShared(string $abstract): bool - { - return isset($this->instances[$abstract]) || - (isset($this->bindings[$abstract]['shared']) && - $this->bindings[$abstract]['shared'] === true); - } - - /** - * Determine if the given concrete is buildable. - * - * @param mixed $concrete - * @param string $abstract - * @return bool - */ - protected function isBuildable($concrete, $abstract): bool - { - return $concrete === $abstract || $concrete instanceof Closure; - } - - /** - * Get the alias for an abstract if available. - * - * @param string $abstract - * - * @return string - */ - public function getAlias(string $abstract): string - { - return isset($this->aliases[$abstract]) - ? $this->getAlias($this->aliases[$abstract]) - : $abstract; - } - - /** - * Get the container's bindings. - * - * @return array - */ - public function getBindings(): array - { - return $this->bindings; - } - - /** - * Drop all of the stale instances and aliases. - * - * @param string $abstract - * @return void - */ - protected function dropStaleInstances($abstract): void - { - unset($this->instances[$abstract], $this->aliases[$abstract]); - } - - /** - * Remove a resolved instance from the instance cache. - * - * @param string $abstract - * @return void - */ - public function forgetInstance($abstract): void - { - unset($this->instances[$abstract]); - } - - /** - * Clear all of the instances from the container. - * - * @return void - */ - public function forgetInstances(): void - { - $this->instances = array(); - } - - /** - * Flush the container of all bindings and resolved instances. - * - * @return void - */ - public function flush(): void - { - $this->aliases = []; - $this->resolved = []; - $this->bindings = []; - $this->instances = []; - $this->abstractAliases = []; - } - - /** - * Determine if a given offset exists. - * - * @param string $key - * @return bool - */ - public function offsetExists($key): bool - { - return $this->bound($key); - } - - /** - * Get the value at a given offset. - * - * @param string $key - * - * @return mixed - * @throws BindingResolutionException - * @throws ReflectionException - */ - public function offsetGet($key): mixed - { - return $this->make($key); - } - - /** - * Set the value at a given offset. - * - * @param string $key - * @param mixed $value - * - * @return void - * @throws BindingResolutionException - * @throws ReflectionException - */ - public function offsetSet($key, $value): void - { - // If the value is not a Closure, we will make it one. This simply gives - // more "drop-in" replacement functionality for the Pimple which this - // container's simplest functions are base modeled and built after. - if ( ! $value instanceof Closure) - { - $value = function() use ($value) - { - return $value; - }; - } - - $this->bind($key, $value); - } - - /** - * Unset the value at a given offset. - * - * @param string $key - * @return void - */ - public function offsetUnset($key): void - { - unset($this->bindings[$key], $this->instances[$key], $this->resolved[$key]); - } - - /** - * Dynamically access container services. - * - * @param string $key - * @return mixed - */ - public function __get($key) - { - return $this[$key]; - } - - /** - * Dynamically set container services. - * - * @param string $key - * @param mixed $value - * @return void - */ - public function __set($key, $value) - { - $this[$key] = $value; - } - -} diff --git a/src/Illuminate/Container/ContainerExtendTest.php b/src/Illuminate/Container/ContainerExtendTest.php deleted file mode 100644 index fd8ff2038..000000000 --- a/src/Illuminate/Container/ContainerExtendTest.php +++ /dev/null @@ -1,188 +0,0 @@ -extend('foo', function ($old, $container) { - return $old.'bar'; - }); - - $this->assertSame('foobar', $container->make('foo')); - - $container = new Container; - - $container->singleton('foo', function () { - return (object) ['name' => 'taylor']; - }); - $container->extend('foo', function ($old, $container) { - $old->age = 26; - - return $old; - }); - - $result = $container->make('foo'); - - $this->assertSame('taylor', $result->name); - $this->assertEquals(26, $result->age); - $this->assertSame($result, $container->make('foo')); - } - - public function testExtendInstancesArePreserved(): void - { - $container = new Container; - $container->bind('foo', function () { - $obj = new stdClass; - $obj->foo = 'bar'; - - return $obj; - }); - - $obj = new stdClass; - $obj->foo = 'foo'; - $container->instance('foo', $obj); - $container->extend('foo', function ($obj, $container) { - $obj->bar = 'baz'; - - return $obj; - }); - $container->extend('foo', function ($obj, $container) { - $obj->baz = 'foo'; - - return $obj; - }); - - $this->assertSame('foo', $container->make('foo')->foo); - $this->assertSame('baz', $container->make('foo')->bar); - $this->assertSame('foo', $container->make('foo')->baz); - } - - public function testExtendIsLazyInitialized(): void - { - ContainerLazyExtendStub::$initialized = false; - - $container = new Container; - $container->bind(ContainerLazyExtendStub::class); - $container->extend(ContainerLazyExtendStub::class, function ($obj, $container) { - $obj->init(); - - return $obj; - }); - $this->assertFalse(ContainerLazyExtendStub::$initialized); - $container->make(ContainerLazyExtendStub::class); - $this->assertTrue(ContainerLazyExtendStub::$initialized); - } - - public function testExtendInstanceRebindingCallback(): void - { - $_SERVER['_test_rebind'] = false; - - $container = new Container; - $container->rebinding('foo', function () { - $_SERVER['_test_rebind'] = true; - }); - - $obj = new stdClass; - $container->instance('foo', $obj); - - $container->extend('foo', function ($obj, $container) { - return $obj; - }); - - $this->assertTrue($_SERVER['_test_rebind']); - } - - public function testExtendBindRebindingCallback(): void - { - $_SERVER['_test_rebind'] = false; - - $container = new Container; - $container->rebinding('foo', function () { - $_SERVER['_test_rebind'] = true; - }); - $container->bind('foo', function () { - return new stdClass; - }); - - $this->assertFalse($_SERVER['_test_rebind']); - - $container->make('foo'); - - $container->extend('foo', function ($obj, $container) { - return $obj; - }); - - $this->assertTrue($_SERVER['_test_rebind']); - } - - public function testExtensionWorksOnAliasedBindings(): void - { - $container = new Container; - $container->singleton('something', function () { - return 'some value'; - }); - $container->alias('something', 'something-alias'); - $container->extend('something-alias', function ($value) { - return $value.' extended'; - }); - - $this->assertSame('some value extended', $container->make('something')); - } - - public function testMultipleExtends(): void - { - $container = new Container; - $container['foo'] = 'foo'; - $container->extend('foo', function ($old, $container) { - return $old.'bar'; - }); - $container->extend('foo', function ($old, $container) { - return $old.'baz'; - }); - - $this->assertSame('foobarbaz', $container->make('foo')); - } - - public function testUnsetExtend(): void - { - $container = new Container; - $container->bind('foo', function () { - $obj = new stdClass; - $obj->foo = 'bar'; - - return $obj; - }); - - $container->extend('foo', function ($obj, $container) { - $obj->bar = 'baz'; - - return $obj; - }); - - unset($container['foo']); - $container->forgetExtenders('foo'); - - $container->bind('foo', function () { - return 'foo'; - }); - - $this->assertSame('foo', $container->make('foo')); - } -} - -class ContainerLazyExtendStub -{ - public static $initialized = false; - - public function init(): void - { - static::$initialized = true; - } -} diff --git a/src/Illuminate/Container/ContextualBindingBuilder.php b/src/Illuminate/Container/ContextualBindingBuilder.php deleted file mode 100644 index b5995b62d..000000000 --- a/src/Illuminate/Container/ContextualBindingBuilder.php +++ /dev/null @@ -1,92 +0,0 @@ -concrete = $concrete; - $this->container = $container; - } - - /** - * Define the abstract target that depends on the context. - * - * @param string $abstract - * - * @return ContextualBindingBuilder - */ - public function needs(string $abstract): ContextualBindingBuilder - { - $this->needs = $abstract; - - return $this; - } - - /** - * Define the implementation for the contextual binding. - * - * @param \Closure|string|array $implementation - * @return void - */ - public function give($implementation): void - { - foreach (Arr::wrap($this->concrete) as $concrete) { - $this->container->addContextualBinding($concrete, $this->needs, $implementation); - } - } - - /** - * Define tagged services to be used as the implementation for the contextual binding. - * - * @param string $tag - * @return void - */ - public function giveTagged($tag): void - { - $this->give(function ($container) use ($tag) { - $taggedServices = $container->tagged($tag); - - return is_array($taggedServices) ? $taggedServices : iterator_to_array($taggedServices); - }); - } - - /** - * Specify the configuration item to bind as a primitive. - * - * @param string $key - * @param mixed $default - * @return void - */ - public function giveConfig($key, $default = null): void - { - $this->give(fn ($container) => $container['config']->get($key, $default)); - } -} \ No newline at end of file diff --git a/src/Illuminate/Container/EntryNotFoundException.php b/src/Illuminate/Container/EntryNotFoundException.php deleted file mode 100644 index bb2ef2ade..000000000 --- a/src/Illuminate/Container/EntryNotFoundException.php +++ /dev/null @@ -1,8 +0,0 @@ -count = $count; - $this->generator = $generator; - } - - /** - * Get an iterator from the generator. - * - * @return \Traversable - */ - public function getIterator(): Traversable - { - return ($this->generator)(); - } - - /** - * Get the total number of tagged services. - * - * @return int - */ - public function count(): int - { - if (is_callable($count = $this->count)) { - $this->count = $count(); - } - - return $this->count; - } -} diff --git a/src/Illuminate/Container/composer.json b/src/Illuminate/Container/composer.json deleted file mode 100755 index a2445f183..000000000 --- a/src/Illuminate/Container/composer.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "illuminate/container", - "license": "MIT", - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylorotwell@gmail.com" - } - ], - "require": { - "php": ">=5.4.0" - }, - "autoload": { - "psr-0": { - "Illuminate\\Container": "" - } - }, - "target-dir": "Illuminate/Container", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, - "minimum-stability": "dev" -} diff --git a/src/Illuminate/Contracts/Auth/Authenticatable.php b/src/Illuminate/Contracts/Auth/Authenticatable.php deleted file mode 100644 index 4e5a80061..000000000 --- a/src/Illuminate/Contracts/Auth/Authenticatable.php +++ /dev/null @@ -1,14 +0,0 @@ -class = $class; - $this->id = $id; - $this->relations = $relations; - $this->connection = $connection; - } - - public function useCollectionClass(?string $collectionClass) - { - $this->collectionClass = $collectionClass; - return $this; - } - - public function getClass(): ?string - { - return $this->class; - } -} diff --git a/src/Illuminate/Contracts/Encryption/DecryptException.php b/src/Illuminate/Contracts/Encryption/DecryptException.php deleted file mode 100644 index 7edebc9ca..000000000 --- a/src/Illuminate/Contracts/Encryption/DecryptException.php +++ /dev/null @@ -1,10 +0,0 @@ -app->bindShared('cookie', function($app) + $this->app->singleton('cookie', function($app) { $config = $app['config']['session']; diff --git a/src/Illuminate/Database/DatabaseServiceProvider.php b/src/Illuminate/Database/DatabaseServiceProvider.php index 492642225..32005da56 100755 --- a/src/Illuminate/Database/DatabaseServiceProvider.php +++ b/src/Illuminate/Database/DatabaseServiceProvider.php @@ -28,7 +28,7 @@ public function register() // 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->bindShared('db.factory', function($app) + $this->app->singleton('db.factory', function($app) { return new ConnectionFactory($app); }); @@ -36,7 +36,7 @@ public function register() // 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->bindShared('db', function($app) + $this->app->singleton('db', function($app) { return new DatabaseManager($app, $app['db.factory']); }); diff --git a/src/Illuminate/Database/Eloquent/Collection.php b/src/Illuminate/Database/Eloquent/Collection.php index 67d7b6bf4..0460b96cb 100755 --- a/src/Illuminate/Database/Eloquent/Collection.php +++ b/src/Illuminate/Database/Eloquent/Collection.php @@ -82,7 +82,6 @@ public function contains($key, $operator = null, $value = null) * @param string $key * @return static */ - #[\Override] public function fetch($key) { return new static(array_fetch($this->toArray(), $key)); diff --git a/src/Illuminate/Database/MigrationServiceProvider.php b/src/Illuminate/Database/MigrationServiceProvider.php index 4bf1d2e73..58782c869 100755 --- a/src/Illuminate/Database/MigrationServiceProvider.php +++ b/src/Illuminate/Database/MigrationServiceProvider.php @@ -44,7 +44,7 @@ public function register() */ protected function registerRepository() { - $this->app->bindShared('migration.repository', function($app) + $this->app->singleton('migration.repository', function($app) { $table = $app['config']['database.migrations']; @@ -62,7 +62,7 @@ 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->bindShared('migrator', function($app) + $this->app->singleton('migrator', function($app) { $repository = $app['migration.repository']; @@ -104,7 +104,7 @@ protected function registerCommands() */ protected function registerMigrateCommand() { - $this->app->bindShared('command.migrate', function($app) + $this->app->singleton('command.migrate', function($app) { $packagePath = $app['path.base'].'/vendor'; @@ -119,7 +119,7 @@ protected function registerMigrateCommand() */ protected function registerRollbackCommand() { - $this->app->bindShared('command.migrate.rollback', function($app) + $this->app->singleton('command.migrate.rollback', function($app) { return new RollbackCommand($app['migrator']); }); @@ -132,7 +132,7 @@ protected function registerRollbackCommand() */ protected function registerResetCommand() { - $this->app->bindShared('command.migrate.reset', function($app) + $this->app->singleton('command.migrate.reset', function($app) { return new ResetCommand($app['migrator']); }); @@ -145,7 +145,7 @@ protected function registerResetCommand() */ protected function registerRefreshCommand() { - $this->app->bindShared('command.migrate.refresh', function() + $this->app->singleton('command.migrate.refresh', function() { return new RefreshCommand; }); @@ -158,7 +158,7 @@ protected function registerRefreshCommand() */ protected function registerInstallCommand() { - $this->app->bindShared('command.migrate.install', function($app) + $this->app->singleton('command.migrate.install', function($app) { return new InstallCommand($app['migration.repository']); }); @@ -173,7 +173,7 @@ protected function registerMakeCommand() { $this->registerCreator(); - $this->app->bindShared('command.migrate.make', function($app) + $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 @@ -193,7 +193,7 @@ protected function registerMakeCommand() */ protected function registerCreator() { - $this->app->bindShared('migration.creator', function($app) + $this->app->singleton('migration.creator', function($app) { return new MigrationCreator($app['files']); }); diff --git a/src/Illuminate/Database/Query/Builder.php b/src/Illuminate/Database/Query/Builder.php index 2bb7b8b3e..974650cf5 100755 --- a/src/Illuminate/Database/Query/Builder.php +++ b/src/Illuminate/Database/Query/Builder.php @@ -1363,14 +1363,14 @@ public function pluck($column, $key = null) // otherwise we can just give these values back without a specific key. $results = new Collection($this->get($columns)); - $values = $results->fetch($columns[0])->all(); + $values = $results->pluck($columns[0])->all(); // If a key was specified and we have results, we will go ahead and combine // the values with the keys of all of the records so that the values can // be accessed by the key of the rows instead of simply being numeric. if ( ! is_null($key) && count($results) > 0) { - $keys = $results->fetch($key)->all(); + $keys = $results->pluck($key)->all(); return array_combine($keys, $values); } diff --git a/src/Illuminate/Database/SeedServiceProvider.php b/src/Illuminate/Database/SeedServiceProvider.php index 00203aa1f..886518ecb 100755 --- a/src/Illuminate/Database/SeedServiceProvider.php +++ b/src/Illuminate/Database/SeedServiceProvider.php @@ -21,7 +21,7 @@ public function register() { $this->registerSeedCommand(); - $this->app->bindShared('seeder', function() + $this->app->singleton('seeder', function() { return new Seeder; }); @@ -36,7 +36,7 @@ public function register() */ protected function registerSeedCommand() { - $this->app->bindShared('command.seed', function($app) + $this->app->singleton('command.seed', function($app) { return new SeedCommand($app['db']); }); diff --git a/src/Illuminate/Encryption/EncryptionServiceProvider.php b/src/Illuminate/Encryption/EncryptionServiceProvider.php index c6329d19e..507192e0e 100755 --- a/src/Illuminate/Encryption/EncryptionServiceProvider.php +++ b/src/Illuminate/Encryption/EncryptionServiceProvider.php @@ -11,7 +11,7 @@ class EncryptionServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('encrypter', function($app) + $this->app->singleton('encrypter', function($app) { return new Encrypter($app['config']['app.key']); }); diff --git a/src/Illuminate/Events/EventServiceProvider.php b/src/Illuminate/Events/EventServiceProvider.php index 94b8e4be3..e78ac72e8 100755 --- a/src/Illuminate/Events/EventServiceProvider.php +++ b/src/Illuminate/Events/EventServiceProvider.php @@ -11,7 +11,7 @@ class EventServiceProvider extends ServiceProvider { */ public function register() { - $this->app['events'] = $this->app->share(function($app) + $this->app->singleton('events', function($app) { return new Dispatcher($app); }); diff --git a/src/Illuminate/Exception/ExceptionServiceProvider.php b/src/Illuminate/Exception/ExceptionServiceProvider.php index c2fa6a68c..0d65df231 100755 --- a/src/Illuminate/Exception/ExceptionServiceProvider.php +++ b/src/Illuminate/Exception/ExceptionServiceProvider.php @@ -38,7 +38,7 @@ protected function registerDisplayers() */ protected function registerHandler() { - $this->app['exception'] = $this->app->share(function($app) + $this->app->singleton('exception', function($app) { return new Handler($app, $app['exception.plain'], $app['exception.debug']); }); @@ -51,7 +51,7 @@ protected function registerHandler() */ protected function registerPlainDisplayer() { - $this->app['exception.plain'] = $this->app->share(function($app) + $this->app->singleton('exception.plain', function($app) { // If the application is running in a console environment, we will just always // use the debug handler as there is no point in the console ever returning @@ -76,7 +76,7 @@ protected function registerDebugDisplayer() { $this->registerWhoops(); - $this->app['exception.debug'] = $this->app->share(function($app) + $this->app->singleton('exception.debug', function($app) { return new WhoopsDisplayer($app['whoops'], $app->runningInConsole()); }); @@ -91,7 +91,7 @@ protected function registerWhoops() { $this->registerWhoopsHandler(); - $this->app['whoops'] = $this->app->share(function($app) + $this->app->singleton('whoops', function($app) { // We will instruct Whoops to not exit after it displays the exception as it // will otherwise run out before we can do anything else. We just want to @@ -113,7 +113,7 @@ protected function registerWhoopsHandler() { if ($this->shouldReturnJson()) { - $this->app['whoops.handler'] = $this->app->share(function() + $this->app->singleton('whoops.handler', function() { return new JsonResponseHandler; }); @@ -151,7 +151,7 @@ protected function requestWantsJson() */ protected function registerPrettyWhoopsHandler() { - $this->app['whoops.handler'] = $this->app->share(function() + $this->app->singleton('whoops.handler', function() { with($handler = new PrettyPageHandler)->setEditor('sublime'); diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index e461fe620..c3fa38fb9 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -2,7 +2,7 @@ use Closure; use Illuminate\Support\Arr; -use Illuminate\Container\BindingResolutionException; +use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Foundation\Http\MiddlewareBuilder; use ReflectionException; use Illuminate\Http\Request; @@ -61,6 +61,14 @@ class Application extends Container implements HttpKernelInterface, TerminableIn */ protected $finishCallbacks = array(); + /** + * ponytail: v13 terminating-callback shim (v13 ServiceProviders register + * these; fork Foundation predates the API). Remove at task 4.5 foundation swap. + * + * @var array + */ + protected $terminatingCallbacks = array(); + /** * The array of shutdown callbacks. * @@ -139,6 +147,11 @@ protected function registerBaseBindings($request) $this->instance('request', $request); $this->instance('Illuminate\Container\Container', $this); + + // v13 code resolves the container via the static Container::getInstance() + // (e.g. BladeCompiler::anonymousComponentPath); register the app as the + // global instance so those calls hit the real bindings/aliases (task 4.3). + static::setInstance($this); } /** @@ -203,6 +216,34 @@ public function bindInstallPaths(array $paths) } } + /** + * Get the path to the resources directory. + * + * ponytail: v13 ServiceProviders (e.g. PaginationServiceProvider) call resourcePath(); + * the L4.2 fork Application lacks it. Remove once Foundation swaps to v13. + * + * @param string $path + * @return string + */ + public function resourcePath($path = '') + { + return $this['path.base'].DIRECTORY_SEPARATOR.'resources'.($path != '' ? DIRECTORY_SEPARATOR.$path : ''); + } + + /** + * Get the base path of the installation. + * + * ponytail: v13 ServiceProviders (e.g. database's MigrationServiceProvider) call basePath(); + * the L4.2 fork Application lacks it. Remove once Foundation swaps to v13. + * + * @param string $path + * @return string + */ + public function basePath($path = '') + { + return $this['path.base'].($path != '' ? DIRECTORY_SEPARATOR.$path : ''); + } + /** * Get the application bootstrap file. * @@ -334,7 +375,10 @@ public function register($provider, $options = array(), $force = false) // If the application has already booted, we will call this boot method on // the provider class so it has an opportunity to do its boot logic and // will be ready for any usage by the developer's application logics. - if ($this->booted) $provider->boot(); + // v13 ServiceProvider has no default boot(); guard + container-call to + // mirror boot() so deferred providers (e.g. RedisServiceProvider) resolved + // after boot don't fatal on a missing boot() method. + if ($this->booted && method_exists($provider, 'boot')) $this->call([$provider, 'boot']); return $provider; } @@ -441,7 +485,12 @@ public function registerDeferredProvider($provider, $service = null) { $this->booting(function() use ($instance) { - $instance->boot(); + // v13 ServiceProvider has no default boot(); call only when defined + // (mirrors the eager boot() loop). Via the container so boot() DI works. + if (method_exists($instance, 'boot')) + { + $this->call([$instance, 'boot']); + } }); } } @@ -472,6 +521,45 @@ public function make($abstract, $parameters = array(), $raiseEvents = true) return parent::make($abstract, $parameters, $raiseEvents); } + /** + * Register a shared binding. + * + * ponytail: transitional BC shim for the L4 container API removed by + * illuminate/container v13. Kept so third-party/vendor providers that still + * call bindShared()/share() on the app (spatie/laravel-blade-x, + * laracasts/commander, tomgrohl/laravel4-php71-encrypter, barryvdh/laravel-ide-helper) + * keep booting. Remove at the Foundation swap (task 4.5); fork src already uses singleton(). + * + * @param string $abstract + * @param \Closure $closure + * @return void + */ + public function bindShared($abstract, Closure $closure): void + { + $this->singleton($abstract, $closure); + } + + /** + * Wrap a closure so the resolved instance is memoized. BC shim; see bindShared(). + * + * @param \Closure $closure + * @return \Closure + */ + public function share(Closure $closure): Closure + { + return function ($container) use ($closure) + { + static $object; + + if (is_null($object)) + { + $object = $closure($container); + } + + return $object; + }; + } + /** * Determine if the given abstract type has been bound. * @@ -545,6 +633,32 @@ public function finish($callback) $this->finishCallbacks[] = $callback; } + /** + * ponytail: v13 Foundation exposes getNamespace() (root PSR-4 namespace) which + * v13's ComponentTagCompiler calls to locate CLASS components. The app uses only + * anonymous components, so the value is never matched — return a benign default + * instead of parsing composer.json. Remove at task 4.5 foundation swap. + * + * @return string + */ + public function getNamespace() + { + return 'App\\'; + } + + /** + * Register a terminating callback (v13 API; see $terminatingCallbacks). + * + * @param callable $callback + * @return $this + */ + public function terminating(callable $callback) + { + $this->terminatingCallbacks[] = $callback; + + return $this; + } + /** * Register a "shutdown" callback. * @@ -596,7 +710,11 @@ public function boot() { if ($this->booted) return; - array_walk($this->serviceProviders, function($p) { $p->boot(); }); + array_walk($this->serviceProviders, function($p) { + // v13 ServiceProvider has no default boot(); call only when defined (via + // the container so boot() method-injection keeps working). + if (method_exists($p, 'boot')) $this->call([$p, 'boot']); + }); $this->bootApplication(); } @@ -806,6 +924,11 @@ public function terminate(SymfonyRequest $request, SymfonyResponse $response): v { $this->callFinishCallbacks($request, $response); + foreach ($this->terminatingCallbacks as $terminating) + { + $this->call($terminating); + } + $this->shutdown(); } @@ -1137,11 +1260,10 @@ public function registerCoreContainerAliases() 'translator' => 'Illuminate\Translation\Translator', 'log' => 'Illuminate\Log\Logger', 'mailer' => 'Illuminate\Mail\Mailer', - 'paginator' => 'Illuminate\Pagination\Factory', 'auth.reminder' => 'Illuminate\Auth\Reminders\PasswordBroker', 'queue' => 'Illuminate\Queue\QueueManager', 'redirect' => 'Illuminate\Routing\Redirector', - 'redis' => 'Illuminate\Redis\Database', + 'redis' => 'Illuminate\Redis\RedisManager', 'request' => 'Illuminate\Http\Request', 'router' => 'Illuminate\Routing\Router', 'session' => 'Illuminate\Session\SessionManager', @@ -1166,6 +1288,32 @@ public function registerCoreContainerAliases() // BC: Hashing\HasherInterface → Contracts\Hashing\Hasher (task 2.11); keep old name resolvable. // class_alias covers use/typehint/instanceof; make()/autowiring by the old name needs this. $this->alias('hash', 'Illuminate\Hashing\HasherInterface'); + + // L13 SCC-1 swap (task 4.1): the swapped components ship v13 contracts. Alias them to + // the core bindings so v13 code that type-hints the contracts resolves (the v13 + // providers don't always register these against the fork's core aliases). + $this->alias('events', 'Illuminate\Contracts\Events\Dispatcher'); + $this->alias('redis', 'Illuminate\Contracts\Redis\Factory'); + $this->alias('cache', 'Illuminate\Contracts\Cache\Factory'); + $this->alias('cache.store', 'Illuminate\Contracts\Cache\Repository'); + $this->alias('config', 'Illuminate\Contracts\Config\Repository'); + $this->alias('db', 'Illuminate\Database\ConnectionResolverInterface'); + + // L13 view swap (task 4.3): v13 view internals (component rendering) resolve + // the Factory contract; alias it to the 'view' binding. + $this->alias('view', 'Illuminate\Contracts\View\Factory'); + + // v13 component rendering autowires the Application/Container contracts; + // mirror v13's 'app' alias cluster (task 4.3). + $this->alias('app', 'Illuminate\Contracts\Foundation\Application'); + $this->alias('app', 'Illuminate\Contracts\Container\Container'); + $this->alias('app', 'Psr\Container\ContainerInterface'); + + // ponytail: v13's Support\Facades\Artisan resolves Illuminate\Contracts\Console\Kernel. + // The fork has no console Kernel (task 4.2); 'artisan' is a lazy singleton + // (ArtisanServiceProvider), so alias the contract to it globally — works for the + // Artisan facade in web/console/tests (make()-only aliasing missed Artisan::call()). + $this->alias('artisan', 'Illuminate\Contracts\Console\Kernel'); } } diff --git a/src/Illuminate/Foundation/Artisan.php b/src/Illuminate/Foundation/Artisan.php index 2b6f23daa..317af4955 100755 --- a/src/Illuminate/Foundation/Artisan.php +++ b/src/Illuminate/Foundation/Artisan.php @@ -40,9 +40,37 @@ protected function getArtisan() $this->app->loadDeferredProviders(); - $this->artisan = ConsoleApplication::make($this->app); + // Boot the app before building the console (the old Console\Application::make() did this): + // provider boot()s register runtime extensions — e.g. the app's custom auth driver via + // Auth::extend — that command resolution depends on. + $this->app->boot(); - return $this->artisan->boot(); + // v13's Console\Application self-bootstraps in its constructor (dispatches ArtisanStarting + // and runs the starting() callbacks registered by ServiceProvider::commands()). It has no + // make()/start()/boot(). ponytail: the L4.2 static bootstrap — rebinding 'artisan' to the + // console so the Artisan facade in start/artisan.php resolves it, then loading that file — + // is inlined here until the Foundation Kernel lands (task 4.5). + $console = new ConsoleApplication($this->app, $this->app['events'], $this->app::VERSION); + + $this->app->instance('artisan', $console); + + // Memoize before requiring start/artisan.php: that file calls Artisan::add() ~149x, and the + // Artisan facade has already cached THIS wrapper, so each add() re-enters __call()->getArtisan(). + // Without the early memo it re-boots + re-requires artisan.php recursively (OOM). With it, the + // re-entrant getArtisan() short-circuits and add() forwards to the console instance. + $this->artisan = $console; + + $path = $this->app['path'].'/start/artisan.php'; + + if (file_exists($path)) require $path; + + // v13 registers attribute-named commands (#[AsCommand]) lazily into a commandMap; they + // only become resolvable once the container command loader is attached (the v13 Kernel + // does the same after resolving). Without this, e.g. illuminate/database's migrate stays + // invisible. Called last, so the map is complete (ctor bootstrappers + start/artisan.php). + $console->setContainerCommandLoader(); + + return $this->artisan = $console; } /** diff --git a/src/Illuminate/Foundation/Console/AssetPublishCommand.php b/src/Illuminate/Foundation/Console/AssetPublishCommand.php index 0b553fff9..1898d75c3 100755 --- a/src/Illuminate/Foundation/Console/AssetPublishCommand.php +++ b/src/Illuminate/Foundation/Console/AssetPublishCommand.php @@ -47,7 +47,7 @@ public function __construct(AssetPublisher $assets) * * @return int */ - public function fire() + public function handle() { foreach ($this->getPackages() as $package) { diff --git a/src/Illuminate/Foundation/Console/AutoloadCommand.php b/src/Illuminate/Foundation/Console/AutoloadCommand.php index bf5ad7d0b..c009ae22a 100755 --- a/src/Illuminate/Foundation/Console/AutoloadCommand.php +++ b/src/Illuminate/Foundation/Console/AutoloadCommand.php @@ -1,7 +1,7 @@ call('optimize'); diff --git a/src/Illuminate/Foundation/Console/ChangesCommand.php b/src/Illuminate/Foundation/Console/ChangesCommand.php index f3cf9788a..7622148e1 100755 --- a/src/Illuminate/Foundation/Console/ChangesCommand.php +++ b/src/Illuminate/Foundation/Console/ChangesCommand.php @@ -24,7 +24,7 @@ class ChangesCommand extends Command { * * @return int */ - public function fire() + public function handle() { list($version, $changes) = $this->getChangeVersion($this->getChangesArray()); diff --git a/src/Illuminate/Foundation/Console/ClearCompiledCommand.php b/src/Illuminate/Foundation/Console/ClearCompiledCommand.php index be9e7c35b..5619be365 100755 --- a/src/Illuminate/Foundation/Console/ClearCompiledCommand.php +++ b/src/Illuminate/Foundation/Console/ClearCompiledCommand.php @@ -23,7 +23,7 @@ class ClearCompiledCommand extends Command { * * @return int */ - public function fire() + public function handle() { if (file_exists($path = $this->laravel['path.base'].'/bootstrap/compiled.php')) { diff --git a/src/Illuminate/Foundation/Console/CommandMakeCommand.php b/src/Illuminate/Foundation/Console/CommandMakeCommand.php index 91e1aed6f..c489fc889 100755 --- a/src/Illuminate/Foundation/Console/CommandMakeCommand.php +++ b/src/Illuminate/Foundation/Console/CommandMakeCommand.php @@ -41,7 +41,7 @@ public function __construct(Filesystem $files) * * @return int */ - public function fire() + public function handle() { $path = $this->getPath(); diff --git a/src/Illuminate/Foundation/Console/ConfigPublishCommand.php b/src/Illuminate/Foundation/Console/ConfigPublishCommand.php index 3b9685468..46a30c78a 100755 --- a/src/Illuminate/Foundation/Console/ConfigPublishCommand.php +++ b/src/Illuminate/Foundation/Console/ConfigPublishCommand.php @@ -49,7 +49,7 @@ public function __construct(ConfigPublisher $config) * * @return int */ - public function fire() + public function handle() { $package = $this->input->getArgument('package'); diff --git a/src/Illuminate/Foundation/Console/DownCommand.php b/src/Illuminate/Foundation/Console/DownCommand.php index 21afba391..d6d57d13f 100755 --- a/src/Illuminate/Foundation/Console/DownCommand.php +++ b/src/Illuminate/Foundation/Console/DownCommand.php @@ -23,7 +23,7 @@ class DownCommand extends Command { * * @return int */ - public function fire() + public function handle() { touch($this->laravel['config']['app.manifest'].'/down'); diff --git a/src/Illuminate/Foundation/Console/EnvironmentCommand.php b/src/Illuminate/Foundation/Console/EnvironmentCommand.php index b6036203d..cfe9606d5 100755 --- a/src/Illuminate/Foundation/Console/EnvironmentCommand.php +++ b/src/Illuminate/Foundation/Console/EnvironmentCommand.php @@ -23,7 +23,7 @@ class EnvironmentCommand extends Command { * * @return int */ - public function fire() + public function handle() { $this->line('Current application environment: '.$this->laravel['env'].''); diff --git a/src/Illuminate/Foundation/Console/KeyGenerateCommand.php b/src/Illuminate/Foundation/Console/KeyGenerateCommand.php index 32cb73d09..8c749bf7b 100755 --- a/src/Illuminate/Foundation/Console/KeyGenerateCommand.php +++ b/src/Illuminate/Foundation/Console/KeyGenerateCommand.php @@ -40,7 +40,7 @@ public function __construct(Filesystem $files) * * @return int */ - public function fire() + public function handle() { list($path, $contents) = $this->getKeyFile(); diff --git a/src/Illuminate/Foundation/Console/MigratePublishCommand.php b/src/Illuminate/Foundation/Console/MigratePublishCommand.php index f2720ab7a..b248c2c2e 100644 --- a/src/Illuminate/Foundation/Console/MigratePublishCommand.php +++ b/src/Illuminate/Foundation/Console/MigratePublishCommand.php @@ -24,7 +24,7 @@ class MigratePublishCommand extends Command { * * @return int */ - public function fire() + public function handle() { $published = $this->laravel['migration.publisher']->publish( $this->getSourcePath(), $this->laravel['path'].'/database/migrations' diff --git a/src/Illuminate/Foundation/Console/OptimizeCommand.php b/src/Illuminate/Foundation/Console/OptimizeCommand.php index c3d4be8ea..2cbdbdac6 100644 --- a/src/Illuminate/Foundation/Console/OptimizeCommand.php +++ b/src/Illuminate/Foundation/Console/OptimizeCommand.php @@ -1,7 +1,7 @@ info('Generating optimized class loader'); if ($this->option('psr')) { - $process = $this->composer->dumpAutoloads(); + $this->composer->dumpAutoloads(); } elseif ($this->option('apcu')) { - $process = $this->composer->dumpAutoloads('--optimize --apcu'); + $this->composer->dumpAutoloads('--optimize --apcu'); } else { - $process = $this->composer->dumpOptimized(); + $this->composer->dumpOptimized(); } - $this->info("Executed: {$process->getCommandLine()}"); - if ($this->option('force') || ! $this->laravel['config']['app.debug']) { $this->info('Compiling views'); diff --git a/src/Illuminate/Foundation/Console/RoutesCommand.php b/src/Illuminate/Foundation/Console/RoutesCommand.php index eec91314a..3c1603a3c 100755 --- a/src/Illuminate/Foundation/Console/RoutesCommand.php +++ b/src/Illuminate/Foundation/Console/RoutesCommand.php @@ -65,7 +65,7 @@ public function __construct(Router $router) * * @return int */ - public function fire() + public function handle() { if (count($this->routes) == 0) { diff --git a/src/Illuminate/Foundation/Console/ServeCommand.php b/src/Illuminate/Foundation/Console/ServeCommand.php index 41c282bea..ba514581b 100755 --- a/src/Illuminate/Foundation/Console/ServeCommand.php +++ b/src/Illuminate/Foundation/Console/ServeCommand.php @@ -24,7 +24,7 @@ class ServeCommand extends Command { * * @return int */ - public function fire() + public function handle() { $this->checkPhpVersion(); diff --git a/src/Illuminate/Foundation/Console/TinkerCommand.php b/src/Illuminate/Foundation/Console/TinkerCommand.php index 3e7b41a84..f55da9696 100755 --- a/src/Illuminate/Foundation/Console/TinkerCommand.php +++ b/src/Illuminate/Foundation/Console/TinkerCommand.php @@ -24,7 +24,7 @@ class TinkerCommand extends Command { * * @return int */ - public function fire() + public function handle() { if ($this->supportsBoris()) { diff --git a/src/Illuminate/Foundation/Console/UpCommand.php b/src/Illuminate/Foundation/Console/UpCommand.php index 7787994b0..0c565d60b 100755 --- a/src/Illuminate/Foundation/Console/UpCommand.php +++ b/src/Illuminate/Foundation/Console/UpCommand.php @@ -23,7 +23,7 @@ class UpCommand extends Command { * * @return int */ - public function fire() + public function handle() { @unlink($this->laravel['config']['app.manifest'].'/down'); diff --git a/src/Illuminate/Foundation/Console/ViewPublishCommand.php b/src/Illuminate/Foundation/Console/ViewPublishCommand.php index 787b31327..7e939c278 100755 --- a/src/Illuminate/Foundation/Console/ViewPublishCommand.php +++ b/src/Illuminate/Foundation/Console/ViewPublishCommand.php @@ -46,7 +46,7 @@ public function __construct(ViewPublisher $view) * * @return int */ - public function fire() + public function handle() { $package = $this->input->getArgument('package'); diff --git a/src/Illuminate/Foundation/Console/stubs/command.stub b/src/Illuminate/Foundation/Console/stubs/command.stub index d48e67534..6a98d455d 100755 --- a/src/Illuminate/Foundation/Console/stubs/command.stub +++ b/src/Illuminate/Foundation/Console/stubs/command.stub @@ -35,7 +35,7 @@ class {{class}} extends Command { * * @return mixed */ - public function fire() + public function handle() { // } diff --git a/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php b/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php index 916175c9c..659e812d4 100755 --- a/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php @@ -21,17 +21,17 @@ class ArtisanServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('artisan', function($app) + $this->app->singleton('artisan', function($app) { return new Artisan($app); }); - $this->app->bindShared('command.changes', function() + $this->app->singleton('command.changes', function() { return new ChangesCommand; }); - $this->app->bindShared('command.environment', function() + $this->app->singleton('command.environment', function() { return new EnvironmentCommand; }); diff --git a/src/Illuminate/Foundation/Providers/CommandCreatorServiceProvider.php b/src/Illuminate/Foundation/Providers/CommandCreatorServiceProvider.php index 560921949..3679effe8 100755 --- a/src/Illuminate/Foundation/Providers/CommandCreatorServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/CommandCreatorServiceProvider.php @@ -19,7 +19,7 @@ class CommandCreatorServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('command.command.make', function($app) + $this->app->singleton('command.command.make', function($app) { return new CommandMakeCommand($app['files']); }); diff --git a/src/Illuminate/Foundation/Providers/ComposerServiceProvider.php b/src/Illuminate/Foundation/Providers/ComposerServiceProvider.php index 2022d7f54..b5e66bdf1 100755 --- a/src/Illuminate/Foundation/Providers/ComposerServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/ComposerServiceProvider.php @@ -1,6 +1,6 @@ app->bindShared('composer', function($app) + $this->app->singleton('composer', function($app) { return new Composer($app['files'], $app['path.base']); }); - $this->app->bindShared('command.dump-autoload', function($app) + $this->app->singleton('command.dump-autoload', function($app) { return new AutoloadCommand($app['composer']); }); diff --git a/src/Illuminate/Foundation/Providers/KeyGeneratorServiceProvider.php b/src/Illuminate/Foundation/Providers/KeyGeneratorServiceProvider.php index f73f93056..197077ddc 100755 --- a/src/Illuminate/Foundation/Providers/KeyGeneratorServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/KeyGeneratorServiceProvider.php @@ -19,7 +19,7 @@ class KeyGeneratorServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('command.key.generate', function($app) + $this->app->singleton('command.key.generate', function($app) { return new KeyGenerateCommand($app['files']); }); diff --git a/src/Illuminate/Foundation/Providers/MaintenanceServiceProvider.php b/src/Illuminate/Foundation/Providers/MaintenanceServiceProvider.php index 703f6d3c0..6de7a4bdc 100755 --- a/src/Illuminate/Foundation/Providers/MaintenanceServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/MaintenanceServiceProvider.php @@ -20,12 +20,12 @@ class MaintenanceServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('command.up', function() + $this->app->singleton('command.up', function() { return new UpCommand; }); - $this->app->bindShared('command.down', function() + $this->app->singleton('command.down', function() { return new DownCommand; }); diff --git a/src/Illuminate/Foundation/Providers/OptimizeServiceProvider.php b/src/Illuminate/Foundation/Providers/OptimizeServiceProvider.php index cc809bc5b..f780fa857 100755 --- a/src/Illuminate/Foundation/Providers/OptimizeServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/OptimizeServiceProvider.php @@ -34,7 +34,7 @@ public function register() */ protected function registerOptimizeCommand() { - $this->app->bindShared('command.optimize', function($app) + $this->app->singleton('command.optimize', function($app) { return new OptimizeCommand($app['composer']); }); @@ -47,7 +47,7 @@ protected function registerOptimizeCommand() */ protected function registerClearCompiledCommand() { - $this->app->bindShared('command.clear-compiled', function() + $this->app->singleton('command.clear-compiled', function() { return new ClearCompiledCommand; }); diff --git a/src/Illuminate/Foundation/Providers/PublisherServiceProvider.php b/src/Illuminate/Foundation/Providers/PublisherServiceProvider.php index ee324c9cf..085b83a96 100755 --- a/src/Illuminate/Foundation/Providers/PublisherServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/PublisherServiceProvider.php @@ -49,7 +49,7 @@ protected function registerAssetPublisher() { $this->registerAssetPublishCommand(); - $this->app->bindShared('asset.publisher', function($app) + $this->app->singleton('asset.publisher', function($app) { $publicPath = $app['path.public']; @@ -71,7 +71,7 @@ protected function registerAssetPublisher() */ protected function registerAssetPublishCommand() { - $this->app->bindShared('command.asset.publish', function($app) + $this->app->singleton('command.asset.publish', function($app) { return new AssetPublishCommand($app['asset.publisher']); }); @@ -86,7 +86,7 @@ protected function registerConfigPublisher() { $this->registerConfigPublishCommand(); - $this->app->bindShared('config.publisher', function($app) + $this->app->singleton('config.publisher', function($app) { $path = $app['path'].'/config'; @@ -108,7 +108,7 @@ protected function registerConfigPublisher() */ protected function registerConfigPublishCommand() { - $this->app->bindShared('command.config.publish', function($app) + $this->app->singleton('command.config.publish', function($app) { return new ConfigPublishCommand($app['config.publisher']); }); @@ -123,7 +123,7 @@ protected function registerViewPublisher() { $this->registerViewPublishCommand(); - $this->app->bindShared('view.publisher', function($app) + $this->app->singleton('view.publisher', function($app) { $viewPath = $app['path'].'/views'; @@ -145,7 +145,7 @@ protected function registerViewPublisher() */ protected function registerViewPublishCommand() { - $this->app->bindShared('command.view.publish', function($app) + $this->app->singleton('command.view.publish', function($app) { return new ViewPublishCommand($app['view.publisher']); }); @@ -160,7 +160,7 @@ protected function registerMigrationPublisher() { $this->registerMigratePublishCommand(); - $this->app->bindShared('migration.publisher', function($app) + $this->app->singleton('migration.publisher', function($app) { return new MigrationPublisher($app['files']); }); @@ -173,7 +173,7 @@ protected function registerMigrationPublisher() */ protected function registerMigratePublishCommand() { - $this->app->bindShared('command.migrate.publish', function() + $this->app->singleton('command.migrate.publish', function() { return new MigratePublishCommand; }); diff --git a/src/Illuminate/Foundation/Providers/RouteListServiceProvider.php b/src/Illuminate/Foundation/Providers/RouteListServiceProvider.php index af1e9bae8..02179b545 100755 --- a/src/Illuminate/Foundation/Providers/RouteListServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/RouteListServiceProvider.php @@ -19,7 +19,7 @@ class RouteListServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('command.routes', function($app) + $this->app->singleton('command.routes', function($app) { return new RoutesCommand($app['router']); }); diff --git a/src/Illuminate/Foundation/Providers/ServerServiceProvider.php b/src/Illuminate/Foundation/Providers/ServerServiceProvider.php index f6af6197e..3e3762b93 100755 --- a/src/Illuminate/Foundation/Providers/ServerServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/ServerServiceProvider.php @@ -19,7 +19,7 @@ class ServerServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('command.serve', function() + $this->app->singleton('command.serve', function() { return new ServeCommand; }); diff --git a/src/Illuminate/Foundation/Providers/TinkerServiceProvider.php b/src/Illuminate/Foundation/Providers/TinkerServiceProvider.php index 55a4a2303..502bbf1cc 100755 --- a/src/Illuminate/Foundation/Providers/TinkerServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/TinkerServiceProvider.php @@ -19,7 +19,7 @@ class TinkerServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('command.tinker', function() + $this->app->singleton('command.tinker', function() { return new TinkerCommand; }); diff --git a/src/Illuminate/Foundation/Testing/Client.php b/src/Illuminate/Foundation/Testing/Client.php index e97ea39a6..086bf2ffc 100755 --- a/src/Illuminate/Foundation/Testing/Client.php +++ b/src/Illuminate/Foundation/Testing/Client.php @@ -21,6 +21,30 @@ protected function filterRequest(DomRequest $request): \Symfony\Component\HttpFo return $httpRequest; } + /** + * v13 Request::convertUploadedFiles() re-wraps each file via UploadedFile::createFromBase() + * with test=false, so a plain Symfony upload fails isValid()/mimes under tests. Handing back + * Illuminate\Http\UploadedFile instances lets that instanceof check preserve the test flag. + */ + #[\Override] + protected function filterFiles(array $files): array + { + return $this->toTestUploadedFiles(parent::filterFiles($files)); + } + + private function toTestUploadedFiles(array $files): array + { + foreach ($files as $key => $file) { + if (is_array($file)) { + $files[$key] = $this->toTestUploadedFiles($file); + } elseif ($file instanceof \Symfony\Component\HttpFoundation\File\UploadedFile) { + $files[$key] = \Illuminate\Http\UploadedFile::createFromBase($file, true); + } + } + + return $files; + } + /** * Get the request parameters from a BrowserKit request. * diff --git a/src/Illuminate/Hashing/HashServiceProvider.php b/src/Illuminate/Hashing/HashServiceProvider.php index 59af2927c..486bf6e4a 100755 --- a/src/Illuminate/Hashing/HashServiceProvider.php +++ b/src/Illuminate/Hashing/HashServiceProvider.php @@ -18,7 +18,7 @@ class HashServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('hash', function() { return new BcryptHasher; }); + $this->app->singleton('hash', function() { return new BcryptHasher; }); } /** diff --git a/src/Illuminate/Html/HtmlServiceProvider.php b/src/Illuminate/Html/HtmlServiceProvider.php index 8cec79adf..7944b486a 100755 --- a/src/Illuminate/Html/HtmlServiceProvider.php +++ b/src/Illuminate/Html/HtmlServiceProvider.php @@ -30,7 +30,7 @@ public function register() */ protected function registerHtmlBuilder() { - $this->app->bindShared('html', function($app) + $this->app->singleton('html', function($app) { return new HtmlBuilder($app['url']); }); @@ -43,9 +43,9 @@ protected function registerHtmlBuilder() */ protected function registerFormBuilder() { - $this->app->bindShared('form', function($app) + $this->app->singleton('form', function($app) { - $form = new FormBuilder($app['html'], $app['url'], $app['session.store']->getToken()); + $form = new FormBuilder($app['html'], $app['url'], $app['session.store']->token()); return $form->setSessionStore($app['session.store']); }); diff --git a/src/Illuminate/Mail/MailServiceProvider.php b/src/Illuminate/Mail/MailServiceProvider.php index 47053d382..7ffda452c 100755 --- a/src/Illuminate/Mail/MailServiceProvider.php +++ b/src/Illuminate/Mail/MailServiceProvider.php @@ -27,7 +27,7 @@ public function register(): void { $me = $this; - $this->app->bindShared('mailer', function($app) use ($me) + $this->app->singleton('mailer', function($app) use ($me) { $me->registerSymfonyMailer(); @@ -59,6 +59,10 @@ public function register(): void return $mailer; }); + + // ponytail: v13 Support\Facades\Mail resolves 'mail.manager'; fork Mail is unswapped and + // binds 'mailer'. Alias so Mail::send() works. Remove when Mail swaps to illuminate/mail:^13. + $this->app->alias('mailer', 'mail.manager'); } /** @@ -120,7 +124,7 @@ public function registerSymfonyMailer(): void */ protected function registerSmtpTransport(array $config): void { - $this->app['symfony.transport'] = $this->app->share(function($app) use ($config) + $this->app->singleton('symfony.transport', function($app) use ($config) { $factory = new EsmtpTransportFactory(); @@ -166,7 +170,7 @@ protected function registerSmtpTransport(array $config): void */ protected function registerSendmailTransport(array $config): void { - $this->app['symfony.transport'] = $this->app->share(fn($app) => new SendmailTransport( + $this->app->singleton('symfony.transport', fn($app) => new SendmailTransport( $config['path'] ?? $app['config']->get('mail.sendmail') )); } @@ -179,7 +183,7 @@ protected function registerSendmailTransport(array $config): void */ protected function registerMailTransport(array $config): void { - $this->app['symfony.transport'] = $this->app->share(fn() => new SendmailTransport()); + $this->app->singleton('symfony.transport', fn() => new SendmailTransport()); } /** @@ -190,7 +194,7 @@ protected function registerMailTransport(array $config): void */ // protected function registerMailgunTransport(array $config): void // { -// $this->app->bindShared('symfony.transport', function() use ($config) +// $this->app->singleton('symfony.transport', function() use ($config) // { // $factory = new MailgunTransportFactory(null, $this->getHttpClient($config)); // @@ -215,7 +219,7 @@ protected function registerMailTransport(array $config): void */ protected function registerLogTransport(array $config): void { - $this->app->bindShared('symfony.transport', fn($app) => new LogTransport($app->make('Psr\Log\LoggerInterface'))); + $this->app->singleton('symfony.transport', fn($app) => new LogTransport($app->make('Psr\Log\LoggerInterface'))); } // /** @@ -244,7 +248,7 @@ protected function registerLogTransport(array $config): void #[\Override] public function provides(): array { - return ['mailer', 'symfony.transport']; + return ['mailer', 'mail.manager', 'symfony.transport']; } } diff --git a/src/Illuminate/Pagination/BootstrapPresenter.php b/src/Illuminate/Pagination/BootstrapPresenter.php deleted file mode 100644 index dc9c7c24f..000000000 --- a/src/Illuminate/Pagination/BootstrapPresenter.php +++ /dev/null @@ -1,42 +0,0 @@ -'.$page.''; - } - - /** - * Get HTML wrapper for disabled text. - * - * @param string $text - * @return string - */ - public function getDisabledTextWrapper($text) - { - return '
  • '.$text.'
  • '; - } - - /** - * Get HTML wrapper for active text. - * - * @param string $text - * @return string - */ - public function getActivePageWrapper($text) - { - return '
  • '.$text.'
  • '; - } - -} diff --git a/src/Illuminate/Pagination/Factory.php b/src/Illuminate/Pagination/Factory.php deleted file mode 100755 index 43a707998..000000000 --- a/src/Illuminate/Pagination/Factory.php +++ /dev/null @@ -1,289 +0,0 @@ -view = $view; - $this->trans = $trans; - $this->request = $request; - $this->pageName = $pageName; - $this->setupPaginationEnvironment(); - } - - /** - * Setup the pagination environment. - * - * @return void - */ - protected function setupPaginationEnvironment() - { - $this->view->addNamespace('pagination', __DIR__.'/views'); - } - - /** - * Get a new paginator instance. - * - * @param array $items - * @param int $total - * @param int|null $perPage - * @return \Illuminate\Pagination\Paginator - */ - public function make(array $items, $total, $perPage = null) - { - $paginator = new Paginator($this, $items, $total, $perPage); - - return $paginator->setupPaginationContext(); - } - - /** - * Get the pagination view. - * - * @param \Illuminate\Pagination\Paginator $paginator - * @param string $view - * @return \Illuminate\View\View - */ - public function getPaginationView(Paginator $paginator, $view = null) - { - $data = array('environment' => $this, 'paginator' => $paginator); - - return $this->view->make($this->getViewName($view), $data); - } - - /** - * Get the number of the current page. - * - * @return int - */ - public function getCurrentPage() - { - $page = (int) $this->currentPage ?: $this->request->input($this->pageName, 1); - - if ($page < 1 || filter_var($page, FILTER_VALIDATE_INT) === false) - { - return 1; - } - - return $page; - } - - /** - * Set the number of the current page. - * - * @param int $number - * @return void - */ - public function setCurrentPage($number) - { - $this->currentPage = $number; - } - - /** - * Get the root URL for the request. - * - * @return string - */ - public function getCurrentUrl() - { - return $this->baseUrl ?: $this->request->url(); - } - - /** - * Set the base URL in use by the paginator. - * - * @param string $baseUrl - * @return void - */ - public function setBaseUrl($baseUrl) - { - $this->baseUrl = $baseUrl; - } - - /** - * Set the input page parameter name used by the paginator. - * - * @param string $pageName - * @return void - */ - public function setPageName($pageName) - { - $this->pageName = $pageName; - } - - /** - * Get the input page parameter name used by the paginator. - * - * @return string - */ - public function getPageName() - { - return $this->pageName; - } - - /** - * Get the name of the pagination view. - * - * @param string $view - * @return string - */ - public function getViewName($view = null) - { - if ( ! is_null($view)) return $view; - - return $this->viewName ?: 'pagination::slider'; - } - - /** - * Set the name of the pagination view. - * - * @param string $viewName - * @return void - */ - public function setViewName($viewName) - { - $this->viewName = $viewName; - } - - /** - * Get the locale of the paginator. - * - * @return string - */ - public function getLocale() - { - return $this->locale; - } - - /** - * Set the locale of the paginator. - * - * @param string $locale - * @return void - */ - public function setLocale($locale) - { - $this->locale = $locale; - } - - /** - * Get the active request instance. - * - * @return \Symfony\Component\HttpFoundation\Request - */ - public function getRequest() - { - return $this->request; - } - - /** - * Set the active request instance. - * - * @param \Symfony\Component\HttpFoundation\Request $request - * @return void - */ - public function setRequest(Request $request) - { - $this->request = $request; - } - - /** - * Get the current view factory. - * - * @return \Illuminate\View\Factory - */ - public function getViewFactory() - { - return $this->view; - } - - /** - * Set the current view factory. - * - * @param \Illuminate\View\Factory $view - * @return void - */ - public function setViewFactory(ViewFactory $view) - { - $this->view = $view; - } - - /** - * Get the translator instance. - * - * @return \Symfony\Contracts\Translation\TranslatorInterface - */ - public function getTranslator() - { - return $this->trans; - } - -} diff --git a/src/Illuminate/Pagination/PaginationServiceProvider.php b/src/Illuminate/Pagination/PaginationServiceProvider.php deleted file mode 100755 index 955ffb15e..000000000 --- a/src/Illuminate/Pagination/PaginationServiceProvider.php +++ /dev/null @@ -1,44 +0,0 @@ -app->bindShared('paginator', function($app) - { - $paginator = new Factory($app['request'], $app['view'], $app['translator']); - - $paginator->setViewName($app['config']['view.pagination']); - - $app->refresh('request', $paginator, 'setRequest'); - - return $paginator; - }); - } - - /** - * Get the services provided by the provider. - * - * @return array - */ - #[\Override] - public function provides() - { - return array('paginator'); - } - -} diff --git a/src/Illuminate/Pagination/Paginator.php b/src/Illuminate/Pagination/Paginator.php deleted file mode 100755 index 121ef27ef..000000000 --- a/src/Illuminate/Pagination/Paginator.php +++ /dev/null @@ -1,545 +0,0 @@ -factory = $factory; - - if (is_null($perPage)) - { - $this->perPage = (int) $total; - $this->hasMore = count($items) > $this->perPage; - $this->items = array_slice($items, 0, $this->perPage); - } - else - { - $this->items = $items; - $this->total = (int) $total; - $this->perPage = (int) $perPage; - } - } - - /** - * Setup the pagination context (current and last page). - * - * @return $this - */ - public function setupPaginationContext() - { - $this->calculateCurrentAndLastPages(); - - $this->calculateItemRanges(); - - return $this; - } - - /** - * Calculate the current and last pages for this instance. - * - * @return void - */ - protected function calculateCurrentAndLastPages() - { - if ($this->isQuickPaginating()) - { - $this->currentPage = $this->factory->getCurrentPage(); - - $this->lastPage = $this->hasMore ? $this->currentPage + 1 : $this->currentPage; - } - else - { - $this->lastPage = max((int) ceil($this->total / $this->perPage), 1); - - $this->currentPage = $this->calculateCurrentPage($this->lastPage); - } - } - - /** - * Calculate the first and last item number for this instance. - * - * @return void - */ - protected function calculateItemRanges() - { - $this->from = $this->total ? ($this->currentPage - 1) * $this->perPage + 1 : 0; - - $this->to = min($this->total, $this->currentPage * $this->perPage); - } - - /** - * Get the current page for the request. - * - * @param int $lastPage - * @return int - */ - protected function calculateCurrentPage($lastPage) - { - $page = $this->factory->getCurrentPage(); - - // The page number will get validated and adjusted if it either less than one - // or greater than the last page available based on the count of the given - // items array. If it's greater than the last, we'll give back the last. - if (is_numeric($page) && $page > $lastPage) - { - return $lastPage > 0 ? $lastPage : 1; - } - - return $this->isValidPageNumber($page) ? (int) $page : 1; - } - - /** - * Determine if the given value is a valid page number. - * - * @param int $page - * @return bool - */ - protected function isValidPageNumber($page) - { - return $page >= 1 && filter_var($page, FILTER_VALIDATE_INT) !== false; - } - - /** - * Get the pagination links view. - * - * @param string $view - * @return \Illuminate\View\View - */ - public function links($view = null) - { - return $this->factory->getPaginationView($this, $view); - } - - /** - * Get a URL for a given page number. - * - * @param int $page - * @return string - */ - public function getUrl($page) - { - $parameters = array( - $this->factory->getPageName() => $page, - ); - - // If we have any extra query string key / value pairs that need to be added - // onto the URL, we will put them in query string form and then attach it - // to the URL. This allows for extra information like sortings storage. - if (count($this->query) > 0) - { - $parameters = array_merge($this->query, $parameters); - } - - $fragment = $this->buildFragment(); - - return $this->factory->getCurrentUrl().'?'.http_build_query($parameters, '', '&').$fragment; - } - - /** - * Get / set the URL fragment to be appended to URLs. - * - * @param string|null $fragment - * @return $this|string - */ - public function fragment($fragment = null) - { - if (is_null($fragment)) return $this->fragment; - - $this->fragment = $fragment; - - return $this; - } - - /** - * Build the full fragment portion of a URL. - * - * @return string - */ - protected function buildFragment() - { - return $this->fragment ? '#'.$this->fragment : ''; - } - - /** - * Add a query string value to the paginator. - * - * @param string $key - * @param string $value - * @return $this - */ - public function appends($key, $value = null) - { - if (is_array($key)) return $this->appendArray($key); - - return $this->addQuery($key, $value); - } - - /** - * Add an array of query string values. - * - * @param array $keys - * @return $this - */ - protected function appendArray(array $keys) - { - foreach ($keys as $key => $value) - { - $this->addQuery($key, $value); - } - - return $this; - } - - /** - * Add a query string value to the paginator. - * - * @param string $key - * @param string $value - * @return $this - */ - public function addQuery($key, $value) - { - if ($key !== $this->factory->getPageName()) - { - $this->query[$key] = $value; - } - - return $this; - } - - /** - * Determine if the paginator is doing "quick" pagination. - * - * @return bool - */ - public function isQuickPaginating() - { - return is_null($this->total); - } - - /** - * Get the current page for the request. - * - * @param int|null $total - * @return int - */ - public function currentPage($total = null) - { - if (is_null($total)) - { - return $this->currentPage; - } - - return min($this->currentPage, (int) ceil($total / $this->perPage)); - } - - /** - * Get the last page that should be available. - * - * @return int - */ - public function lastPage() - { - return $this->lastPage; - } - - /** - * Get the number of the first item on the paginator. - * - * @return int - */ - public function firstItem() - { - return $this->from; - } - - /** - * Get the number of the last item on the paginator. - * - * @return int - */ - public function lastItem() - { - return $this->to; - } - - /** - * Get the number of items to be displayed per page. - * - * @return int - */ - public function perPage() - { - return $this->perPage; - } - - /** - * Get a collection instance containing the items. - * - * @return \Illuminate\Support\Collection - */ - public function getCollection() - { - return new Collection($this->items); - } - - /** - * Get the items being paginated. - * - * @return array - */ - public function items() - { - return $this->items; - } - - /** - * Set the items being paginated. - * - * @param mixed $items - * @return void - */ - public function setItems($items) - { - $this->items = $items; - } - - /** - * Get the total number of items in the collection. - * - * @return int - */ - public function total() - { - return $this->total; - } - - /** - * Set the base URL in use by the paginator. - * - * @param string $baseUrl - * @return void - */ - public function setBaseUrl($baseUrl) - { - $this->factory->setBaseUrl($baseUrl); - } - - /** - * Get the pagination factory. - * - * @return \Illuminate\Pagination\Factory - */ - public function getFactory() - { - return $this->factory; - } - - /** - * Get an iterator for the items. - * - * @return \ArrayIterator - */ - public function getIterator(): Traversable - { - return new ArrayIterator($this->items); - } - - /** - * Determine if the list of items is empty or not. - * - * @return bool - */ - public function isEmpty() - { - return empty($this->items); - } - - /** - * Get the number of items for the current page. - * - * @return int - */ - public function count(): int - { - return count($this->items); - } - - /** - * Determine if the given item exists. - * - * @param mixed $key - * @return bool - */ - public function offsetExists($key): bool - { - return array_key_exists($key, $this->items); - } - - /** - * Get the item at the given offset. - * - * @param mixed $key - * @return mixed - */ - public function offsetGet($key): mixed - { - return $this->items[$key]; - } - - /** - * Set the item at the given offset. - * - * @param mixed $key - * @param mixed $value - * @return void - */ - public function offsetSet($key, $value): void - { - $this->items[$key] = $value; - } - - /** - * Unset the item at the given key. - * - * @param mixed $key - * @return void - */ - public function offsetUnset($key): void - { - unset($this->items[$key]); - } - - /** - * Get the instance as an array. - * - * @return array - */ - public function toArray() - { - return array( - 'total' => $this->total, 'per_page' => $this->perPage, - 'current_page' => $this->currentPage, 'last_page' => $this->lastPage, - 'from' => $this->from, 'to' => $this->to, 'data' => $this->getCollection()->toArray(), - ); - } - - /** - * Convert the object to its JSON representation. - * - * @param int $options - * @return string - */ - public function toJson($options = 0) - { - return json_encode($this->toArray(), $options); - } - - /** - * Call a method on the underlying Collection - * - * @param string $method - * @param array $arguments - * @return mixed - */ - public function __call($method, $arguments) - { - return call_user_func_array(array($this->getCollection(), $method), $arguments); - } - -} diff --git a/src/Illuminate/Pagination/Presenter.php b/src/Illuminate/Pagination/Presenter.php deleted file mode 100755 index 42a9eb789..000000000 --- a/src/Illuminate/Pagination/Presenter.php +++ /dev/null @@ -1,277 +0,0 @@ -paginator = $paginator; - $this->lastPage = $this->paginator->lastPage(); - $this->currentPage = $this->paginator->currentPage(); - } - - /** - * Get HTML wrapper for a page link. - * - * @param string $url - * @param int $page - * @param string $rel - * @return string - */ - abstract public function getPageLinkWrapper($url, $page, $rel = null); - - /** - * Get HTML wrapper for disabled text. - * - * @param string $text - * @return string - */ - abstract public function getDisabledTextWrapper($text); - - /** - * Get HTML wrapper for active text. - * - * @param string $text - * @return string - */ - abstract public function getActivePageWrapper($text); - - /** - * Render the Pagination contents. - * - * @return string - */ - public function render() - { - // The hard-coded thirteen represents the minimum number of pages we need to - // be able to create a sliding page window. If we have less than that, we - // will just render a simple range of page links insteadof the sliding. - if ($this->lastPage < 13) - { - $content = $this->getPageRange(1, $this->lastPage); - } - else - { - $content = $this->getPageSlider(); - } - - return $this->getPrevious().$content.$this->getNext(); - } - - /** - * Create a range of pagination links. - * - * @param int $start - * @param int $end - * @return string - */ - public function getPageRange($start, $end) - { - $pages = array(); - - for ($page = $start; $page <= $end; $page++) - { - // If the current page is equal to the page we're iterating on, we will create a - // disabled link for that page. Otherwise, we can create a typical active one - // for the link. We will use this implementing class's methods to get HTML. - if ($this->currentPage == $page) - { - $pages[] = $this->getActivePageWrapper($page); - } - else - { - $pages[] = $this->getLink($page); - } - } - - return implode('', $pages); - } - - /** - * Create a pagination slider link window. - * - * @return string - */ - protected function getPageSlider() - { - $window = 6; - - // If the current page is very close to the beginning of the page range, we will - // just render the beginning of the page range, followed by the last 2 of the - // links in this list, since we will not have room to create a full slider. - if ($this->currentPage <= $window) - { - $ending = $this->getFinish(); - - return $this->getPageRange(1, $window + 2).$ending; - } - - // If the current page is close to the ending of the page range we will just get - // this first couple pages, followed by a larger window of these ending pages - // since we're too close to the end of the list to create a full on slider. - elseif ($this->currentPage >= $this->lastPage - $window) - { - $start = $this->lastPage - 8; - - $content = $this->getPageRange($start, $this->lastPage); - - return $this->getStart().$content; - } - - // If we have enough room on both sides of the current page to build a slider we - // will surround it with both the beginning and ending caps, with this window - // of pages in the middle providing a Google style sliding paginator setup. - else - { - $content = $this->getAdjacentRange(); - - return $this->getStart().$content.$this->getFinish(); - } - } - - /** - * Get the page range for the current page window. - * - * @return string - */ - public function getAdjacentRange() - { - return $this->getPageRange($this->currentPage - 3, $this->currentPage + 3); - } - - /** - * Create the beginning leader of a pagination slider. - * - * @return string - */ - public function getStart() - { - return $this->getPageRange(1, 2).$this->getDots(); - } - - /** - * Create the ending cap of a pagination slider. - * - * @return string - */ - public function getFinish() - { - $content = $this->getPageRange($this->lastPage - 1, $this->lastPage); - - return $this->getDots().$content; - } - - /** - * Get the previous page pagination element. - * - * @param string $text - * @return string - */ - public function getPrevious($text = '«') - { - // If the current page is less than or equal to one, it means we can't go any - // further back in the pages, so we will render a disabled previous button - // when that is the case. Otherwise, we will give it an active "status". - if ($this->currentPage <= 1) - { - return $this->getDisabledTextWrapper($text); - } - - $url = $this->paginator->getUrl($this->currentPage - 1); - - return $this->getPageLinkWrapper($url, $text, 'prev'); - } - - /** - * Get the next page pagination element. - * - * @param string $text - * @return string - */ - public function getNext($text = '»') - { - // If the current page is greater than or equal to the last page, it means we - // can't go any further into the pages, as we're already on this last page - // that is available, so we will make it the "next" link style disabled. - if ($this->currentPage >= $this->lastPage) - { - return $this->getDisabledTextWrapper($text); - } - - $url = $this->paginator->getUrl($this->currentPage + 1); - - return $this->getPageLinkWrapper($url, $text, 'next'); - } - - /** - * Get a pagination "dot" element. - * - * @return string - */ - public function getDots() - { - return $this->getDisabledTextWrapper("..."); - } - - /** - * Create a pagination slider link. - * - * @param mixed $page - * @return string - */ - public function getLink($page) - { - $url = $this->paginator->getUrl($page); - - return $this->getPageLinkWrapper($url, $page); - } - - /** - * Set the value of the current page. - * - * @param int $page - * @return void - */ - public function setCurrentPage($page) - { - $this->currentPage = $page; - } - - /** - * Set the value of the last page. - * - * @param int $page - * @return void - */ - public function setLastPage($page) - { - $this->lastPage = $page; - } - -} diff --git a/src/Illuminate/Pagination/composer.json b/src/Illuminate/Pagination/composer.json deleted file mode 100755 index 96c959f82..000000000 --- a/src/Illuminate/Pagination/composer.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "illuminate/pagination", - "license": "MIT", - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylorotwell@gmail.com" - } - ], - "require": { - "php": ">=5.4.0", - "illuminate/http": "4.2.*", - "illuminate/support": "4.2.*", - "illuminate/view": "4.2.*", - "symfony/http-foundation": "~6.4", - "symfony/translation": "~6.4" - }, - "autoload": { - "psr-0": { - "Illuminate\\Pagination": "" - } - }, - "target-dir": "Illuminate/Pagination", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, - "minimum-stability": "dev" -} diff --git a/src/Illuminate/Pagination/views/simple.php b/src/Illuminate/Pagination/views/simple.php deleted file mode 100755 index 36353c327..000000000 --- a/src/Illuminate/Pagination/views/simple.php +++ /dev/null @@ -1,15 +0,0 @@ -getTranslator(); -?> - -lastPage() > 1): ?> - - diff --git a/src/Illuminate/Pagination/views/slider-3.php b/src/Illuminate/Pagination/views/slider-3.php deleted file mode 100755 index 0131087bc..000000000 --- a/src/Illuminate/Pagination/views/slider-3.php +++ /dev/null @@ -1,9 +0,0 @@ - - -lastPage() > 1): ?> - - diff --git a/src/Illuminate/Pagination/views/slider.php b/src/Illuminate/Pagination/views/slider.php deleted file mode 100755 index af10c3c90..000000000 --- a/src/Illuminate/Pagination/views/slider.php +++ /dev/null @@ -1,11 +0,0 @@ - - -lastPage() > 1): ?> - - diff --git a/src/Illuminate/Queue/Console/FailedTableCommand.php b/src/Illuminate/Queue/Console/FailedTableCommand.php index 6cbf86320..521002f15 100644 --- a/src/Illuminate/Queue/Console/FailedTableCommand.php +++ b/src/Illuminate/Queue/Console/FailedTableCommand.php @@ -44,7 +44,7 @@ public function __construct(Filesystem $files) * * @return int */ - public function fire() + public function handle() { $fullPath = $this->createBaseMigration(); diff --git a/src/Illuminate/Queue/Console/FlushFailedCommand.php b/src/Illuminate/Queue/Console/FlushFailedCommand.php index 91f6fba91..34e105148 100644 --- a/src/Illuminate/Queue/Console/FlushFailedCommand.php +++ b/src/Illuminate/Queue/Console/FlushFailedCommand.php @@ -22,7 +22,7 @@ class FlushFailedCommand extends Command { * Execute the console command. * */ - public function fire() + public function handle() { $this->laravel['queue.failer']->flush(); diff --git a/src/Illuminate/Queue/Console/ForgetFailedCommand.php b/src/Illuminate/Queue/Console/ForgetFailedCommand.php index 6083ca603..2bd9ad8e1 100644 --- a/src/Illuminate/Queue/Console/ForgetFailedCommand.php +++ b/src/Illuminate/Queue/Console/ForgetFailedCommand.php @@ -24,7 +24,7 @@ class ForgetFailedCommand extends Command { * * @return int */ - public function fire() + public function handle() { if ($this->laravel['queue.failer']->forget($this->argument('id'))) { diff --git a/src/Illuminate/Queue/Console/ListFailedCommand.php b/src/Illuminate/Queue/Console/ListFailedCommand.php index 328c97b9d..2a539fae6 100644 --- a/src/Illuminate/Queue/Console/ListFailedCommand.php +++ b/src/Illuminate/Queue/Console/ListFailedCommand.php @@ -23,7 +23,7 @@ class ListFailedCommand extends Command { * * @return int */ - public function fire() + public function handle() { $rows = array(); @@ -38,11 +38,7 @@ public function fire() return 0; } - $table = $this->getHelperSet()->get('table'); - - $table->setHeaders(array('ID', 'Connection', 'Queue', 'Class', 'Failed At')) - ->setRows($rows) - ->render($this->output); + $this->table(array('ID', 'Connection', 'Queue', 'Class', 'Failed At'), $rows); return 0; } diff --git a/src/Illuminate/Queue/Console/ListenCommand.php b/src/Illuminate/Queue/Console/ListenCommand.php index a07c720d2..b7fed5687 100755 --- a/src/Illuminate/Queue/Console/ListenCommand.php +++ b/src/Illuminate/Queue/Console/ListenCommand.php @@ -46,7 +46,7 @@ public function __construct(Listener $listener) * * @return int */ - public function fire() + public function handle() { $this->setListenerOptions(); diff --git a/src/Illuminate/Queue/Console/RestartCommand.php b/src/Illuminate/Queue/Console/RestartCommand.php index 80313e09e..6ad6f9b72 100644 --- a/src/Illuminate/Queue/Console/RestartCommand.php +++ b/src/Illuminate/Queue/Console/RestartCommand.php @@ -23,7 +23,7 @@ class RestartCommand extends Command { * * @return int */ - public function fire() + public function handle() { $this->laravel['cache']->forever('illuminate:queue:restart', time()); diff --git a/src/Illuminate/Queue/Console/RetryCommand.php b/src/Illuminate/Queue/Console/RetryCommand.php index d75953973..293dec0ab 100644 --- a/src/Illuminate/Queue/Console/RetryCommand.php +++ b/src/Illuminate/Queue/Console/RetryCommand.php @@ -24,7 +24,7 @@ class RetryCommand extends Command { * * @return int */ - public function fire() + public function handle() { $failed = $this->laravel['queue.failer']->find($this->argument('id')); diff --git a/src/Illuminate/Queue/Console/SubscribeCommand.php b/src/Illuminate/Queue/Console/SubscribeCommand.php index c0b6c3e61..7c34d5193 100755 --- a/src/Illuminate/Queue/Console/SubscribeCommand.php +++ b/src/Illuminate/Queue/Console/SubscribeCommand.php @@ -36,7 +36,7 @@ class SubscribeCommand extends Command { * * @throws \RuntimeException */ - public function fire() + public function handle() { $iron = $this->laravel['queue']->connection(); diff --git a/src/Illuminate/Queue/Console/WorkCommand.php b/src/Illuminate/Queue/Console/WorkCommand.php index 8d39b2305..2aca6dbec 100755 --- a/src/Illuminate/Queue/Console/WorkCommand.php +++ b/src/Illuminate/Queue/Console/WorkCommand.php @@ -47,7 +47,7 @@ public function __construct(Worker $worker) * * @return int */ - public function fire() + public function handle() { if ($this->downForMaintenance() && ! $this->option('daemon')) return 0; diff --git a/src/Illuminate/Queue/FailConsoleServiceProvider.php b/src/Illuminate/Queue/FailConsoleServiceProvider.php index c510a0bc3..d2eeaf509 100644 --- a/src/Illuminate/Queue/FailConsoleServiceProvider.php +++ b/src/Illuminate/Queue/FailConsoleServiceProvider.php @@ -23,27 +23,27 @@ class FailConsoleServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('command.queue.failed', function() + $this->app->singleton('command.queue.failed', function() { return new ListFailedCommand; }); - $this->app->bindShared('command.queue.retry', function() + $this->app->singleton('command.queue.retry', function() { return new RetryCommand; }); - $this->app->bindShared('command.queue.forget', function() + $this->app->singleton('command.queue.forget', function() { return new ForgetFailedCommand; }); - $this->app->bindShared('command.queue.flush', function() + $this->app->singleton('command.queue.flush', function() { return new FlushFailedCommand; }); - $this->app->bindShared('command.queue.failed-table', function($app) + $this->app->singleton('command.queue.failed-table', function($app) { return new FailedTableCommand($app['files']); }); diff --git a/src/Illuminate/Queue/QueueServiceProvider.php b/src/Illuminate/Queue/QueueServiceProvider.php index f6829f257..26169c893 100755 --- a/src/Illuminate/Queue/QueueServiceProvider.php +++ b/src/Illuminate/Queue/QueueServiceProvider.php @@ -49,7 +49,7 @@ public function register() */ protected function registerManager() { - $this->app->bindShared('queue', function($app) + $this->app->singleton('queue', function($app) { // Once we have an instance of the queue manager, we will register the various // resolvers for the queue connectors. These connectors are responsible for @@ -73,7 +73,7 @@ protected function registerWorker() $this->registerRestartCommand(); - $this->app->bindShared('queue.worker', function($app) + $this->app->singleton('queue.worker', function($app) { return new Worker($app['queue'], $app['queue.failer'], $app['events']); }); @@ -86,7 +86,7 @@ protected function registerWorker() */ protected function registerWorkCommand() { - $this->app->bindShared('command.queue.work', function($app) + $this->app->singleton('command.queue.work', function($app) { return new WorkCommand($app['queue.worker']); }); @@ -103,7 +103,7 @@ protected function registerListener() { $this->registerListenCommand(); - $this->app->bindShared('queue.listener', function($app) + $this->app->singleton('queue.listener', function($app) { return new Listener($app['path.base']); }); @@ -116,7 +116,7 @@ protected function registerListener() */ protected function registerListenCommand() { - $this->app->bindShared('command.queue.listen', function($app) + $this->app->singleton('command.queue.listen', function($app) { return new ListenCommand($app['queue.listener']); }); @@ -131,7 +131,7 @@ protected function registerListenCommand() */ public function registerRestartCommand() { - $this->app->bindShared('command.queue.restart', function() + $this->app->singleton('command.queue.restart', function() { return new RestartCommand; }); @@ -146,7 +146,7 @@ public function registerRestartCommand() */ protected function registerSubscriber() { - $this->app->bindShared('command.queue.subscribe', function() + $this->app->singleton('command.queue.subscribe', function() { return new SubscribeCommand; }); @@ -267,7 +267,7 @@ protected function registerIronRequestBinder() */ protected function registerFailedJobServices() { - $this->app->bindShared('queue.failer', function($app) + $this->app->singleton('queue.failer', function($app) { $config = $app['config']['queue.failed']; @@ -282,7 +282,7 @@ protected function registerFailedJobServices() */ protected function registerQueueClosure() { - $this->app->bindShared('IlluminateQueueClosure', function($app) + $this->app->singleton('IlluminateQueueClosure', function($app) { return new IlluminateQueueClosure($app['encrypter']); }); diff --git a/src/Illuminate/Redis/RedisServiceProvider.php b/src/Illuminate/Redis/RedisServiceProvider.php index ae2fe9e84..39236a98c 100755 --- a/src/Illuminate/Redis/RedisServiceProvider.php +++ b/src/Illuminate/Redis/RedisServiceProvider.php @@ -18,7 +18,7 @@ class RedisServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('redis', function($app) + $this->app->singleton('redis', function($app) { return new Database($app['config']['database.redis']); }); diff --git a/src/Illuminate/Routing/Console/MakeControllerCommand.php b/src/Illuminate/Routing/Console/MakeControllerCommand.php index 5eeb8e968..594c60b59 100755 --- a/src/Illuminate/Routing/Console/MakeControllerCommand.php +++ b/src/Illuminate/Routing/Console/MakeControllerCommand.php @@ -55,7 +55,7 @@ public function __construct(ControllerGenerator $generator, $path) * * @return int */ - public function fire() + public function handle() { $this->generateController(); diff --git a/src/Illuminate/Routing/ControllerServiceProvider.php b/src/Illuminate/Routing/ControllerServiceProvider.php index ba12f2502..0df75c996 100644 --- a/src/Illuminate/Routing/ControllerServiceProvider.php +++ b/src/Illuminate/Routing/ControllerServiceProvider.php @@ -32,7 +32,7 @@ public function register() */ protected function registerGenerator() { - $this->app->bindShared('command.controller.make', function($app) + $this->app->singleton('command.controller.make', function($app) { // The controller generator is responsible for building resourceful controllers // quickly and easily for the developers via the Artisan CLI. We'll go ahead diff --git a/src/Illuminate/Routing/ResponseFactory.php b/src/Illuminate/Routing/ResponseFactory.php index 226db8d4e..b72f4d8a0 100644 --- a/src/Illuminate/Routing/ResponseFactory.php +++ b/src/Illuminate/Routing/ResponseFactory.php @@ -1,5 +1,7 @@ make('', $status, $headers); + } + + public function file($file, array $headers = []) + { + return new BinaryFileResponse($file, 200, $headers); + } + + public function streamJson($data, $status = 200, $headers = [], $encodingOptions = JsonResponse::DEFAULT_ENCODING_OPTIONS) + { + return new StreamedJsonResponse($data, $status, $headers, $encodingOptions); + } + + public function streamDownload($callback, $name = null, array $headers = [], $disposition = 'attachment') + { + $response = new StreamedResponse($callback, 200, $headers); + + if ( ! is_null($name)) + { + $response->headers->set('Content-Disposition', $response->headers->makeDisposition( + $disposition, $name, str_replace('%', '', Str::ascii($name)) + )); + } + + return $response; + } + + public function eventStream(Closure $callback, array $headers = [], $endStreamWith = '') + { + return $this->stream(function () use ($callback, $endStreamWith) { + foreach ($callback() as $message) + { + if (connection_aborted()) break; + + if ( ! is_string($message) && ! is_numeric($message)) + { + $message = json_encode($message); + } + + echo "event: update\n"; + echo 'data: '.$message; + echo "\n\n"; + + if (ob_get_level() > 0) ob_flush(); + flush(); + } + + if ($endStreamWith !== null && $endStreamWith !== '') + { + echo "event: update\n"; + echo 'data: '.$endStreamWith; + echo "\n\n"; + + if (ob_get_level() > 0) ob_flush(); + flush(); + } + }, 200, array_merge($headers, [ + 'Content-Type' => 'text/event-stream', + 'Cache-Control' => 'no-cache', + 'X-Accel-Buffering' => 'no', + ])); + } + + public function redirectTo($path, $status = 302, $headers = [], $secure = null) + { + return $this->container['redirect']->to($path, $status, $headers, $secure); + } + + public function redirectToRoute($route, $parameters = [], $status = 302, $headers = []) + { + return $this->container['redirect']->route($route, $parameters, $status, $headers); + } + + public function redirectToAction($action, $parameters = [], $status = 302, $headers = []) + { + return $this->container['redirect']->action($action, $parameters, $status, $headers); + } + + public function redirectGuest($path, $status = 302, $headers = [], $secure = null) + { + return $this->container['redirect']->guest($path, $status, $headers, $secure); + } + + public function redirectToIntended($default = '/', $status = 302, $headers = [], $secure = null) + { + return $this->container['redirect']->intended($default, $status, $headers, $secure); + } + } diff --git a/src/Illuminate/Routing/RoutingServiceProvider.php b/src/Illuminate/Routing/RoutingServiceProvider.php index 9d1d078f9..9ef8da535 100755 --- a/src/Illuminate/Routing/RoutingServiceProvider.php +++ b/src/Illuminate/Routing/RoutingServiceProvider.php @@ -27,7 +27,7 @@ public function register() */ protected function registerRouter() { - $this->app['router'] = $this->app->share(function($app) + $this->app->singleton('router', function($app) { $router = new Router($app['events'], $app); @@ -50,7 +50,7 @@ protected function registerRouter() */ protected function registerUrlGenerator() { - $this->app['url'] = $this->app->share(function($app) + $this->app->singleton('url', function($app) { // The URL generator needs the route collection that exists on the router. // Keep in mind this is an object, so we're passing by references here @@ -71,7 +71,7 @@ protected function registerUrlGenerator() */ protected function registerRedirector() { - $this->app['redirect'] = $this->app->share(function($app) + $this->app->singleton('redirect', function($app) { $redirector = new Redirector($app['url']); @@ -94,7 +94,7 @@ protected function registerRedirector() */ protected function registerResponseFactory() { - $this->app[\Illuminate\Contracts\Routing\ResponseFactory::class] = $this->app->share(function($app) + $this->app->singleton(\Illuminate\Contracts\Routing\ResponseFactory::class, function($app) { return new ResponseFactory($app); }); diff --git a/src/Illuminate/Session/CommandsServiceProvider.php b/src/Illuminate/Session/CommandsServiceProvider.php index 5f7b01c71..81ef0baea 100755 --- a/src/Illuminate/Session/CommandsServiceProvider.php +++ b/src/Illuminate/Session/CommandsServiceProvider.php @@ -18,7 +18,7 @@ class CommandsServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('command.session.database', function($app) + $this->app->singleton('command.session.database', function($app) { return new Console\SessionTableCommand($app['files']); }); diff --git a/src/Illuminate/Session/SessionServiceProvider.php b/src/Illuminate/Session/SessionServiceProvider.php index 0efe172de..70fd15213 100755 --- a/src/Illuminate/Session/SessionServiceProvider.php +++ b/src/Illuminate/Session/SessionServiceProvider.php @@ -38,7 +38,7 @@ protected function setupDefaultDriver() */ protected function registerSessionManager() { - $this->app->bindShared('session', function($app) + $this->app->singleton('session', function($app) { return new SessionManager($app); }); @@ -51,7 +51,7 @@ protected function registerSessionManager() */ protected function registerSessionDriver() { - $this->app->bindShared('session.store', function($app) + $this->app->singleton('session.store', function($app) { // First, we will create the session manager which is responsible for the // creation of the various session drivers when they are needed by the diff --git a/src/Illuminate/Support/Arr.php b/src/Illuminate/Support/Arr.php deleted file mode 100755 index 1071c58a8..000000000 --- a/src/Illuminate/Support/Arr.php +++ /dev/null @@ -1,982 +0,0 @@ - $items, - $items instanceof Enumerable => $items->all(), - $items instanceof Arrayable => $items->toArray(), - $items instanceof WeakMap => iterator_to_array($items, false), - $items instanceof Traversable => iterator_to_array($items), - $items instanceof Jsonable => json_decode($items->toJson(), true), - $items instanceof JsonSerializable => (array) $items->jsonSerialize(), - is_object($items) => (array) $items, - default => throw new InvalidArgumentException('Items cannot be represented by a scalar value.'), - }; - } - - /** - * Run an associative map over each of the items. - * - * The callback should return an associative array with a single key/value pair. - * - * @param array $array - * @param callable $callback - * @return array - */ - public static function mapWithKeys(array $array, callable $callback) - { - $result = []; - - foreach ($array as $key => $value) { - $assoc = $callback($value, $key); - - foreach ($assoc as $mapKey => $mapValue) { - $result[$mapKey] = $mapValue; - } - } - - return $result; - } - - /** - * Partition the array into two arrays using the given callback. - * - * @param array $array - * @param callable $callback - * @return array - */ - public static function partition($array, callable $callback) - { - $passed = []; - $failed = []; - - foreach ($array as $key => $item) { - if ($callback($item, $key)) { - $passed[$key] = $item; - } else { - $failed[$key] = $item; - } - } - - return [$passed, $failed]; - } - - /** - * Select an array of values from an array. - * - * @param array $array - * @param array|string $keys - * @return array - */ - public static function select($array, $keys) - { - $keys = static::wrap($keys); - - return static::map($array, function ($item) use ($keys) { - $result = []; - - foreach ($keys as $key) { - if (Arr::accessible($item) && Arr::exists($item, $key)) { - $result[$key] = $item[$key]; - } elseif (is_object($item) && isset($item->{$key})) { - $result[$key] = $item->{$key}; - } - } - - return $result; - }); - } - - /** - * Determine whether the given value is array accessible. - * - * @param mixed $value - * @return bool - */ - public static function accessible($value): bool - { - return is_array($value) || $value instanceof ArrayAccess; - } - - /** - * Add an element to an array using "dot" notation if it doesn't exist. - * - * @param array $array - * @param string $key - * @param mixed $value - * - * @return array - */ - public static function add(array $array, string $key, mixed $value): array - { - if (is_null(static::get($array, $key))) - { - static::set($array, $key, $value); - } - - return $array; - } - - /** - * Build a new array using a callback. - * - * @param array $array - * @param \Closure $callback - * - * @return array - */ - public static function build(array $array, Closure $callback): array - { - $results = array(); - - foreach ($array as $key => $value) - { - [$innerKey, $innerValue] = call_user_func($callback, $key, $value); - - $results[$innerKey] = $innerValue; - } - - return $results; - } - - /** - * Collapse an array of arrays into a single array. - * - * @param iterable $array - * - * @return array - */ - public static function collapse(iterable $array): array - { - $results = []; - - foreach ($array as $values) { - if ($values instanceof Collection) { - $values = $values->all(); - } elseif (! is_array($values)) { - continue; - } - - $results[] = $values; - } - - return array_merge([], ...$results); - } - - /** - * Cross join the given arrays, returning all possible permutations. - * - * @param iterable ...$arrays - * @return array - */ - public static function crossJoin(...$arrays): array - { - $results = [[]]; - - foreach ($arrays as $index => $array) { - $append = []; - - foreach ($results as $product) { - foreach ($array as $item) { - $product[$index] = $item; - - $append[] = $product; - } - } - - $results = $append; - } - - return $results; - } - - /** - * Divide an array into two arrays. One with keys and the other with values. - * - * @param array $array - * - * @return array - */ - public static function divide(array $array): array - { - return array(array_keys($array), array_values($array)); - } - - /** - * Flatten a multi-dimensional associative array with dots. - * - * @param array $array - * @param string $prepend - * - * @return array - */ - public static function dot(array $array, string $prepend = ''): array - { - $results = []; - - foreach ($array as $key => $value) { - if (is_array($value) && ! empty($value)) { - $results = array_merge($results, static::dot($value, $prepend.$key.'.')); - } else { - $results[$prepend.$key] = $value; - } - } - - return $results; - } - - /** - * Convert a flatten "dot" notation array into an expanded array. - * - * @param iterable $array - * - * @return array - */ - public static function undot(iterable $array): array - { - $results = []; - - foreach ($array as $key => $value) { - static::set($results, $key, $value); - } - - return $results; - } - - /** - * Get all of the given array except for a specified array of items. - * - * @param array $array - * @param array|string $keys - * - * @return array - */ - public static function except(array $array, array|string $keys): array - { - static::forget($array, $keys); - - return $array; - } - - /** - * Determine if the given key exists in the provided array. - * - * @param \ArrayAccess|array $array - * @param int|float|string $key - * - * @return bool - */ - public static function exists(ArrayAccess|array $array, $key): bool - { - if ($array instanceof ArrayAccess) { - return $array->offsetExists($key); - } - - if (is_float($key)) { - $key = (string) $key; - } - - return array_key_exists($key, $array); - } - - - /** - * Fetch a flattened array of a nested array element. - * - * @param array $array - * @param string $key - * @return array - */ - public static function fetch($array, $key) - { - foreach (explode('.', $key) as $segment) - { - $results = array(); - - foreach ($array as $value) - { - if (array_key_exists($segment, $value = (array) $value)) - { - $results[] = $value[$segment]; - } - } - - $array = array_values($results); - } - - return array_values($results); - } - - /** - * Return the first element in an array passing a given truth test. - * - * @param array $array - * @param \Closure|null $callback - * @param mixed|null $default - * - * @return mixed - */ - public static function first(array $array, ?Closure $callback = null, mixed $default = null): mixed - { - if (is_null($callback)) { - if (empty($array)) { - return value($default); - } - - foreach ($array as $item) { - return $item; - } - } - - foreach ($array as $key => $value) { - if ($callback($value, $key)) { - return $value; - } - } - - return value($default); - } - - /** - * Join all items using a string. The final items can use a separate glue string. - * - * @param array $array - * @param string $glue - * @param string $finalGlue - * - * @return string - */ - public static function join(array $array, string $glue, string $finalGlue = ''): string - { - if ($finalGlue === '') { - return implode($glue, $array); - } - - if (count($array) === 0) { - return ''; - } - - if (count($array) === 1) { - return end($array); - } - - $finalItem = array_pop($array); - - return implode($glue, $array).$finalGlue.$finalItem; - } - - /** - * Key an associative array by a field or using a callback. - * - * @param array $array - * @param callable|array|string $keyBy - * @return array - */ - public static function keyBy($array, $keyBy): array - { - return Collection::make($array)->keyBy($keyBy)->all(); - } - - /** - * Return the last element in an array passing a given truth test. - * - * @param array $array - * @param \Closure|null $callback - * @param mixed $default - * - * @return mixed - */ - public static function last(array $array, ?Closure $callback = null, $default = null): mixed - { - if (is_null($callback)) { - return empty($array) ? value($default) : end($array); - } - - return static::first(array_reverse($array, true), $callback, $default); - } - - /** - * Flatten a multi-dimensional array into a single level. - * - * @param array $array - * @param int $depth - * - * @return array - */ - public static function flatten(array $array, $depth = INF): array - { - $result = []; - - foreach ($array as $item) { - $item = $item instanceof Collection ? $item->all() : $item; - - if (! is_array($item)) { - $result[] = $item; - } else { - $values = $depth === 1 - ? array_values($item) - : static::flatten($item, $depth - 1); - - foreach ($values as $value) { - $result[] = $value; - } - } - } - - return $result; - } - - /** - * Remove one or many array items from a given array using "dot" notation. - * - * @param array $array - * @param array|string $keys - * @return void - */ - public static function forget(&$array, $keys) - { - $original = &$array; - - $keys = (array) $keys; - - if (count($keys) === 0) { - return; - } - - foreach ($keys as $key) { - // if the exact key exists in the top-level, remove it - if (static::exists($array, $key)) { - unset($array[$key]); - - continue; - } - - $parts = explode('.', $key); - - // clean up before each pass - $array = &$original; - - while (count($parts) > 1) { - $part = array_shift($parts); - - if (isset($array[$part]) && static::accessible($array[$part])) { - $array = &$array[$part]; - } else { - continue 2; - } - } - - unset($array[array_shift($parts)]); - } - } - - /** - * Get an item from an array using "dot" notation. - * - * @param \ArrayAccess|array|null $array - * @param string|null $key - * @param mixed $default - * - * @return mixed - */ - public static function get($array, $key = null, $default = null) - { - if (! static::accessible($array)) { - return value($default); - } - - if (is_null($key)) { - return $array; - } - - if (static::exists($array, $key)) { - return $array[$key]; - } - - if (! str_contains($key, '.')) { - return $array[$key] ?? value($default); - } - - foreach (explode('.', $key) as $segment) { - if (static::accessible($array) && static::exists($array, $segment)) { - $array = $array[$segment]; - } else { - return value($default); - } - } - - return $array; - } - - /** - * Check if an item exists in an array using "dot" notation. - * - * @param \ArrayAccess|array $array - * @param string|array $keys - * @return bool - */ - public static function has($array, $keys): bool - { - $keys = (array) $keys; - - if (! $array || $keys === []) { - return false; - } - - foreach ($keys as $key) { - $subKeyArray = $array; - - if (static::exists($array, $key)) { - continue; - } - - foreach (explode('.', $key) as $segment) { - if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) { - $subKeyArray = $subKeyArray[$segment]; - } else { - return false; - } - } - } - - return true; - } - - /** - * Determine if any of the keys exist in an array using "dot" notation. - * - * @param \ArrayAccess|array $array - * @param string|array $keys - * @return bool - */ - public static function hasAny($array, $keys): bool - { - if (is_null($keys)) { - return false; - } - - $keys = (array) $keys; - - if (! $array) { - return false; - } - - if ($keys === []) { - return false; - } - - foreach ($keys as $key) { - if (static::has($array, $key)) { - return true; - } - } - - return false; - } - - /** - * Determines if an array is associative. - * - * An array is "associative" if it doesn't have sequential numerical keys beginning with zero. - * - * @param array $array - * @return bool - */ - public static function isAssoc(array $array): bool - { - return ! array_is_list($array); - } - - /** - * Determines if an array is a list. - * - * An array is a "list" if all array keys are sequential integers starting from 0 with no gaps in between. - * - * @param array $array - * - * @return bool - */ - public static function isList(array $array): bool - { - return array_is_list($array); - } - - /** - * Run a map over each of the items in the array. - * - * @param array $array - * @param callable $callback - * @return array - */ - public static function map(array $array, callable $callback): array - { - $keys = array_keys($array); - - try { - $items = array_map($callback, $array, $keys); - } catch (ArgumentCountError) { - $items = array_map($callback, $array); - } - - return array_combine($keys, $items); - } - - /** - * Get a subset of the items from the given array. - * - * @param array $array - * @param array|string $keys - * - * @return array - */ - public static function only(array $array, array|string $keys): array - { - return array_intersect_key($array, array_flip((array) $keys)); - } - - /** - * Pluck an array of values from an array. - * - * @param array $array - * @param array|string|null $value - * @param string|null $key - * - * @return array - */ - public static function pluck(array $array, $value = null, $key = null): array - { - $results = []; - - [$value, $key] = static::explodePluckParameters($value, $key); - - foreach ($array as $item) { - $itemValue = data_get($item, $value); - - // If the key is "null", we will just append the value to the array and keep - // looping. Otherwise we will key the array using the value of the key we - // received from the developer. Then we'll return the final array form. - if (is_null($key)) { - $results[] = $itemValue; - } else { - $itemKey = data_get($item, $key); - - if (is_object($itemKey) && method_exists($itemKey, '__toString')) { - $itemKey = (string) $itemKey; - } - - $results[$itemKey] = $itemValue; - } - } - - return $results; - } - - /** - * Explode the "value" and "key" arguments passed to "pluck". - * - * @param string|array $value - * @param string|array|null $key - * @return array - */ - protected static function explodePluckParameters($value, $key): array - { - $value = is_string($value) ? explode('.', $value) : $value; - - $key = is_null($key) || is_array($key) ? $key : explode('.', $key); - - return [$value, $key]; - } - - /** - * Push an item onto the beginning of an array. - * - * @param array $array - * @param mixed $value - * @param mixed $key - * - * @return array - */ - public static function prepend(array $array, $value, $key = null): array - { - if (func_num_args() == 2) { - array_unshift($array, $value); - } else { - $array = [$key => $value] + $array; - } - - return $array; - } - - /** - * Prepend the key names of an associative array. - * - * @param array $array - * @param string $prependWith - * @return array - */ - public static function prependKeysWith($array, $prependWith): array - { - return Collection::make($array)->mapWithKeys(function ($item, $key) use ($prependWith) { - return [$prependWith.$key => $item]; - })->all(); - } - - /** - * Get a value from the array, and remove it. - * - * @param array $array - * @param string $key - * @param mixed $default - * @return mixed - */ - public static function pull(&$array, $key, $default = null) - { - $value = static::get($array, $key, $default); - - static::forget($array, $key); - - return $value; - } - - /** - * Convert the array into a query string. - * - * @param array $array - * @return string - */ - public static function query($array): string - { - return http_build_query($array, '', '&', PHP_QUERY_RFC3986); - } - - /** - * Get one or a specified number of random values from an array. - * - * @param array $array - * @param int|null $number - * @param bool|false $preserveKeys - * @return mixed - * - * @throws \InvalidArgumentException - */ - public static function random($array, $number = null, $preserveKeys = false) - { - $requested = is_null($number) ? 1 : $number; - - $count = count($array); - - if ($requested > $count) { - throw new InvalidArgumentException( - "You requested {$requested} items, but there are only {$count} items available." - ); - } - - if (is_null($number)) { - return $array[array_rand($array)]; - } - - if ((int) $number === 0) { - return []; - } - - $keys = array_rand($array, $number); - - $results = []; - - if ($preserveKeys) { - foreach ((array) $keys as $key) { - $results[$key] = $array[$key]; - } - } else { - foreach ((array) $keys as $key) { - $results[] = $array[$key]; - } - } - - return $results; - } - - /** - * Set an array item to a given value using "dot" notation. - * - * If no key is given to the method, the entire array will be replaced. - * - * @param array $array - * @param string $key - * @param mixed $value - * @return array - */ - public static function set(&$array, $key, $value): array - { - if (is_null($key)) return $array = $value; - - $keys = explode('.', $key); - - while (count($keys) > 1) - { - $key = array_shift($keys); - - // If the key doesn't exist at this depth, we will just create an empty array - // to hold the next value, allowing us to create the arrays to hold final - // values at the correct depth. Then we'll keep digging into the array. - if ( ! isset($array[$key]) || ! is_array($array[$key])) - { - $array[$key] = array(); - } - - $array =& $array[$key]; - } - - $array[array_shift($keys)] = $value; - - return $array; - } - - /** - * Shuffle the given array and return the result. - * - * @param array $array - * @param int|null $seed - * @return array - */ - public static function shuffle($array, $seed = null): array - { - if (is_null($seed)) { - shuffle($array); - } else { - mt_srand($seed); - shuffle($array); - mt_srand(); - } - - return $array; - } - - /** - * Sort the array using the given Closure. - * - * @param array $array - * @param callable|array|string|null $callback - * - * @return array - */ - public static function sort(array $array, $callback = null): array - { - return Collection::make($array)->sortBy($callback)->all(); - } - - /** - * Recursively sort an array by keys and values. - * - * @param array $array - * @param int $options - * @param bool $descending - * @return array - */ - public static function sortRecursive($array, $options = SORT_REGULAR, $descending = false): array - { - foreach ($array as &$value) { - if (is_array($value)) { - $value = static::sortRecursive($value, $options, $descending); - } - } - - if (! array_is_list($array)) { - $descending - ? krsort($array, $options) - : ksort($array, $options); - } else { - $descending - ? rsort($array, $options) - : sort($array, $options); - } - - return $array; - } - - /** - * Conditionally compile classes from an array into a CSS class list. - * - * @param array $array - * - * @return string - */ - public static function toCssClasses(array $array): string - { - $classList = static::wrap($array); - - $classes = []; - - foreach ($classList as $class => $constraint) { - if (is_numeric($class)) { - $classes[] = $constraint; - } elseif ($constraint) { - $classes[] = $class; - } - } - - return implode(' ', $classes); - } - - /** - * Filter the array using the given callback. - * - * @param array $array - * @param callable $callback - * @return array - */ - public static function where($array, callable $callback): array - { - return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH); - } - - /** - * Filter items where the value is not null. - * - * @param array $array - * @return array - */ - public static function whereNotNull($array) - { - return static::where($array, function ($value, $key) { - return ! is_null($value); - }); - } - - /** - * If the given value is not an array and not null, wrap it in one. - * - * @param mixed $value - * @return array - */ - public static function wrap($value): array - { - if (is_null($value)) { - return []; - } - - return is_array($value) ? $value : [$value]; - } -} diff --git a/src/Illuminate/Support/Collection.php b/src/Illuminate/Support/Collection.php deleted file mode 100755 index 01aec5735..000000000 --- a/src/Illuminate/Support/Collection.php +++ /dev/null @@ -1,2050 +0,0 @@ - - * @implements \Illuminate\Support\Enumerable - */ -class Collection implements ArrayAccess, ArrayableInterface, CanBeEscapedWhenCastToString, Enumerable, JsonableInterface -{ - /** - * @use \Illuminate\Support\Traits\EnumeratesValues - */ - use EnumeratesValues, Macroable; - - /** - * The items contained in the collection. - * - * @var array - */ - protected $items = []; - - /** - * Create a new collection. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable|null $items - */ - public function __construct($items = []) - { - $this->items = $this->getArrayableItems($items); - } - - // ponytail: Laravel 4.2 holdovers kept so the fork's Database layer and existing - // callers keep working across the L13 shape change; removed in migration task 2.5 - // (lists → pluck, fetch → pluck) once app call-sites are converted. - - /** - * Get an array with the values of a given key. - * - * @param string $value - * @param string|null $key - * @return array - */ - public function lists(string $value, ?string $key = null): array - { - $results = []; - - foreach ($this->items as $item) { - $itemValue = is_object($item) ? $item->{$value} : $item[$value]; - - if (is_null($key)) { - $results[] = $itemValue; - } else { - $itemKey = is_object($item) ? $item->{$key} : $item[$key]; - - $results[$itemKey] = $itemValue; - } - } - - return $results; - } - - /** - * Fetch a nested element of the collection. - * - * @param string $key - * @return static - */ - public function fetch($key) - { - return new static(array_fetch($this->items, $key)); - } - - /** - * Create a new instance of the collection. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable|null $items - * @return static - */ - protected function newInstance($items = []) - { - return new static($items); - } - - /** - * Create a collection with the given range. - * - * @param int $from - * @param int $to - * @param int $step - * @return static - */ - public static function range($from, $to, $step = 1, ...$args) - { - return new static(range($from, $to, $step), ...$args); - } - - /** - * Get all of the items in the collection. - * - * @return array - */ - public function all() - { - return $this->items; - } - - /** - * Get a lazy collection for the items in this collection. - * - * @return \Illuminate\Support\LazyCollection - */ - public function lazy() - { - return new LazyCollection($this->items); - } - - /** - * Get the median of a given key. - * - * @param string|array|null $key - * @return float|int|null - */ - public function median($key = null) - { - $values = (isset($key) ? $this->pluck($key) : $this) - ->reject(fn ($item) => is_null($item)) - ->sort()->values(); - - $count = $values->count(); - - if ($count === 0) { - return; - } - - $middle = intdiv($count, 2); - - if ($count % 2) { - return $values->get($middle); - } - - return $this->newInstance([ - $values->get($middle - 1), $values->get($middle), - ])->average(); - } - - /** - * Get the mode of a given key. - * - * @param string|array|null $key - * @return array|null - */ - public function mode($key = null) - { - if ($this->isEmpty()) { - return; - } - - $collection = isset($key) ? $this->pluck($key) : $this; - - $counts = $this->newInstance(); - - $collection->each(fn ($value) => $counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1); - - $sorted = $counts->sort(); - - $highestValue = $sorted->last(); - - return $sorted->filter(fn ($value) => $value == $highestValue) - ->sort()->keys()->all(); - } - - /** - * Collapse the collection of items into a single array. - * - * @return static - */ - public function collapse() - { - return $this->newInstance(Arr::collapse($this->items)); - } - - /** - * Collapse the collection of items into a single array while preserving its keys. - * - * @return static - */ - public function collapseWithKeys() - { - if (! $this->items) { - return $this->newInstance(); - } - - $results = []; - - foreach ($this->items as $key => $values) { - if ($values instanceof Collection) { - $values = $values->all(); - } elseif (! is_array($values)) { - continue; - } - - $results[$key] = $values; - } - - if (! $results) { - return $this->newInstance(); - } - - return $this->newInstance(array_replace(...$results)); - } - - /** - * Determine if an item exists in the collection. - * - * @param (callable(TValue, TKey): bool)|TValue|string $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function contains($key, $operator = null, $value = null) - { - if (func_num_args() === 1) { - if ($this->useAsCallable($key)) { - return array_any($this->items, $key); - } - - return in_array($key, $this->items); - } - - return $this->contains($this->operatorForWhere(...func_get_args())); - } - - /** - * Determine if an item exists, using strict comparison. - * - * @param (callable(TValue): bool)|TValue|array-key $key - * @param TValue|null $value - * @return bool - */ - public function containsStrict($key, $value = null) - { - if (func_num_args() === 2) { - return $this->contains(fn ($item) => data_get($item, $key) === $value); - } - - if ($this->useAsCallable($key)) { - return ! is_null($this->first($key)); - } - - return in_array($key, $this->items, true); - } - - /** - * Determine if an item is not contained in the collection. - * - * @param mixed $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function doesntContain($key, $operator = null, $value = null) - { - return ! $this->contains(...func_get_args()); - } - - /** - * Determine if an item is not contained in the enumerable, using strict comparison. - * - * @param mixed $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function doesntContainStrict($key, $operator = null, $value = null) - { - return ! $this->containsStrict(...func_get_args()); - } - - /** - * Cross join with the given lists, returning all possible permutations. - * - * @template TCrossJoinKey - * @template TCrossJoinValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable ...$lists - * @return static> - */ - public function crossJoin(...$lists) - { - return $this->newInstance(Arr::crossJoin( - $this->items, ...array_map($this->getArrayableItems(...), $lists) - )); - } - - /** - * Get the items in the collection that are not present in the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function diff($items) - { - return $this->newInstance(array_diff($this->items, $this->getArrayableItems($items))); - } - - /** - * Get the items in the collection that are not present in the given items, using the callback. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @param callable(TValue, TValue): int $callback - * @return static - */ - public function diffUsing($items, callable $callback) - { - return $this->newInstance(array_udiff($this->items, $this->getArrayableItems($items), $callback)); - } - - /** - * Get the items in the collection whose keys and values are not present in the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function diffAssoc($items) - { - return $this->newInstance(array_diff_assoc($this->items, $this->getArrayableItems($items))); - } - - /** - * Get the items in the collection whose keys and values are not present in the given items, using the callback. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @param callable(TKey, TKey): int $callback - * @return static - */ - public function diffAssocUsing($items, callable $callback) - { - return $this->newInstance(array_diff_uassoc($this->items, $this->getArrayableItems($items), $callback)); - } - - /** - * Get the items in the collection whose keys are not present in the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function diffKeys($items) - { - return $this->newInstance(array_diff_key($this->items, $this->getArrayableItems($items))); - } - - /** - * Get the items in the collection whose keys are not present in the given items, using the callback. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @param callable(TKey, TKey): int $callback - * @return static - */ - public function diffKeysUsing($items, callable $callback) - { - return $this->newInstance(array_diff_ukey($this->items, $this->getArrayableItems($items), $callback)); - } - - /** - * Retrieve duplicate items from the collection. - * - * @template TMapValue - * - * @param (callable(TValue): TMapValue)|string|null $callback - * @param bool $strict - * @return static - */ - public function duplicates($callback = null, $strict = false) - { - $items = $this->map($this->valueRetriever($callback)); - - $uniqueItems = $items->unique(null, $strict); - - $compare = $this->duplicateComparator($strict); - - $duplicates = $this->newInstance(); - - foreach ($items as $key => $value) { - if ($uniqueItems->isNotEmpty() && $compare($value, $uniqueItems->first())) { - $uniqueItems->shift(); - } else { - $duplicates[$key] = $value; - } - } - - return $duplicates; - } - - /** - * Retrieve duplicate items from the collection using strict comparison. - * - * @template TMapValue - * - * @param (callable(TValue): TMapValue)|string|null $callback - * @return static - */ - public function duplicatesStrict($callback = null) - { - return $this->duplicates($callback, true); - } - - /** - * Get the comparison function to detect duplicates. - * - * @param bool $strict - * @return callable(TValue, TValue): bool - */ - protected function duplicateComparator($strict) - { - if ($strict) { - return fn ($a, $b) => $a === $b; - } - - return fn ($a, $b) => $a == $b; - } - - /** - * Get all items except for those with the specified keys. - * - * @param \Illuminate\Support\Enumerable|array|string $keys - * @return static - */ - public function except($keys) - { - if (is_null($keys)) { - return $this->newInstance($this->items); - } - - if ($keys instanceof Enumerable) { - $keys = $keys->all(); - } elseif (! is_array($keys)) { - $keys = func_get_args(); - } - - return $this->newInstance(Arr::except($this->items, $keys)); - } - - /** - * Run a filter over each of the items. - * - * @param (callable(TValue, TKey): bool)|null $callback - * @return static - */ - public function filter(?callable $callback = null) - { - if ($callback) { - return $this->newInstance(Arr::where($this->items, $callback)); - } - - return $this->newInstance(array_filter($this->items)); - } - - /** - * Get the first item from the collection passing the given truth test. - * - * @template TFirstDefault - * - * @param (callable(TValue, TKey): bool)|null $callback - * @param TFirstDefault|(\Closure(): TFirstDefault) $default - * @return TValue|TFirstDefault - */ - public function first(?callable $callback = null, $default = null) - { - return Arr::first($this->items, $callback, $default); - } - - /** - * Get a flattened array of the items in the collection. - * - * @param int $depth - * @return static - */ - public function flatten($depth = INF) - { - return $this->newInstance(Arr::flatten($this->items, $depth)); - } - - /** - * Flip the items in the collection. - * - * @return static - */ - public function flip() - { - return $this->newInstance(array_flip($this->items)); - } - - /** - * Remove an item from the collection by key. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable|TKey $keys - * @return $this - */ - public function forget($keys) - { - foreach ($this->getArrayableItems($keys) as $key) { - $this->offsetUnset($key); - } - - return $this; - } - - /** - * Get an item from the collection by key. - * - * @template TGetDefault - * - * @param TKey|null $key - * @param TGetDefault|(\Closure(): TGetDefault) $default - * @return TValue|TGetDefault - */ - public function get($key, $default = null) - { - $key ??= ''; - - if (array_key_exists($key, $this->items)) { - return $this->items[$key]; - } - - return value($default); - } - - /** - * Get an item from the collection by key or add it to collection if it does not exist. - * - * @template TGetOrPutValue - * - * @param mixed $key - * @param TGetOrPutValue|(\Closure(): TGetOrPutValue) $value - * @return TValue|TGetOrPutValue - */ - public function getOrPut($key, $value) - { - if (array_key_exists($key ?? '', $this->items)) { - return $this->items[$key ?? '']; - } - - $this->offsetSet($key, $value = value($value)); - - return $value; - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function groupBy($groupBy, $preserveKeys = false) - { - if (! $this->useAsCallable($groupBy) && is_array($groupBy)) { - $nextGroups = $groupBy; - - $groupBy = array_shift($nextGroups); - } - - $groupBy = $this->valueRetriever($groupBy); - - $results = []; - - foreach ($this->items as $key => $value) { - $groupKeys = $groupBy($value, $key); - - if (! is_array($groupKeys)) { - $groupKeys = [$groupKeys]; - } - - foreach ($groupKeys as $groupKey) { - $groupKey = match (true) { - is_bool($groupKey) => (int) $groupKey, - $groupKey instanceof \UnitEnum => enum_value($groupKey), - $groupKey instanceof \Stringable, is_null($groupKey) => (string) $groupKey, - default => $groupKey, - }; - - if (! array_key_exists($groupKey, $results)) { - $results[$groupKey] = $this->newInstance(); - } - - $results[$groupKey]->offsetSet($preserveKeys ? $key : null, $value); - } - } - - $result = $this->newInstance($results); - - if (! empty($nextGroups)) { - return $result->map->groupBy($nextGroups, $preserveKeys); - } - - return $result; - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function keyBy($keyBy) - { - $keyBy = $this->valueRetriever($keyBy); - - $results = []; - - foreach ($this->items as $key => $item) { - $resolvedKey = $keyBy($item, $key); - - if ($resolvedKey instanceof \UnitEnum) { - $resolvedKey = enum_value($resolvedKey); - } - - if (is_object($resolvedKey)) { - $resolvedKey = (string) $resolvedKey; - } - - if (is_null($resolvedKey)) { - $resolvedKey = (string) $resolvedKey; - } - - $results[$resolvedKey] = $item; - } - - return $this->newInstance($results); - } - - /** - * Determine if an item exists in the collection by key. - * - * @param TKey|array $key - * @return bool - */ - public function has($key) - { - $keys = is_array($key) ? $key : func_get_args(); - - return array_all($keys, fn ($key) => array_key_exists($key ?? '', $this->items)); - } - - /** - * Determine if any of the keys exist in the collection. - * - * @param TKey|array $key - * @return bool - */ - public function hasAny($key) - { - if ($this->isEmpty()) { - return false; - } - - $keys = is_array($key) ? $key : func_get_args(); - - return array_any($keys, fn ($key) => array_key_exists($key ?? '', $this->items)); - } - - /** - * Concatenate values of a given key as a string. - * - * @param (callable(TValue, TKey): mixed)|string|null $value - * @param string|null $glue - * @return string - */ - public function implode($value, $glue = null) - { - if ($this->useAsCallable($value)) { - return implode($glue ?? '', $this->map($value)->all()); - } - - $first = $this->first(); - - if (is_array($first) || (is_object($first) && ! $first instanceof Stringable)) { - return implode($glue ?? '', $this->pluck($value)->all()); - } - - return implode($value ?? '', $this->items); - } - - /** - * Intersect the collection with the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function intersect($items) - { - return $this->newInstance(array_intersect($this->items, $this->getArrayableItems($items))); - } - - /** - * Intersect the collection with the given items, using the callback. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @param callable(TValue, TValue): int $callback - * @return static - */ - public function intersectUsing($items, callable $callback) - { - return $this->newInstance(array_uintersect($this->items, $this->getArrayableItems($items), $callback)); - } - - /** - * Intersect the collection with the given items with additional index check. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function intersectAssoc($items) - { - return $this->newInstance(array_intersect_assoc($this->items, $this->getArrayableItems($items))); - } - - /** - * Intersect the collection with the given items with additional index check, using the callback. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @param callable(TValue, TValue): int $callback - * @return static - */ - public function intersectAssocUsing($items, callable $callback) - { - return $this->newInstance(array_intersect_uassoc($this->items, $this->getArrayableItems($items), $callback)); - } - - /** - * Intersect the collection with the given items by key. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function intersectByKeys($items) - { - return $this->newInstance(array_intersect_key( - $this->items, $this->getArrayableItems($items) - )); - } - - /** - * Determine if the collection is empty or not. - * - * @phpstan-assert-if-true null $this->first() - * @phpstan-assert-if-true null $this->last() - * - * @phpstan-assert-if-false TValue $this->first() - * @phpstan-assert-if-false TValue $this->last() - * - * @return bool - */ - public function isEmpty() - { - return empty($this->items); - } - - /** - * Determine if the collection contains exactly one item. If a callback is provided, determine if exactly one item matches the condition. - * - * @param (callable(TValue, TKey): bool)|null $callback - * @return bool - * - * @deprecated 12.49.0 Use the `hasSole()` method instead. - */ - public function containsOneItem(?callable $callback = null): bool - { - return $this->hasSole($callback); - } - - /** - * Determine if the collection contains multiple items. - * - * @param (callable(TValue, TKey): bool)|null $callback - * @return bool - * - * @deprecated 12.50.0 Use the `hasMany()` method instead. - */ - public function containsManyItems(?callable $callback = null): bool - { - return $this->hasMany($callback); - } - - /** - * Join all items from the collection using a string. The final items can use a separate glue string. - * - * @param string $glue - * @param string $finalGlue - * @return TValue|string - */ - public function join($glue, $finalGlue = '') - { - if ($finalGlue === '') { - return $this->implode($glue); - } - - $count = $this->count(); - - if ($count === 0) { - return ''; - } - - if ($count === 1) { - return $this->last(); - } - - $collection = $this->newInstance($this->items); - - $finalItem = $collection->pop(); - - return $collection->implode($glue).$finalGlue.$finalItem; - } - - /** - * Get the keys of the collection items. - * - * @return static - */ - public function keys() - { - return $this->newInstance(array_keys($this->items)); - } - - /** - * Get the last item from the collection. - * - * @template TLastDefault - * - * @param (callable(TValue, TKey): bool)|null $callback - * @param TLastDefault|(\Closure(): TLastDefault) $default - * @return TValue|TLastDefault - */ - public function last(?callable $callback = null, $default = null) - { - return Arr::last($this->items, $callback, $default); - } - - /** - * Get the values of a given key. - * - * @param \Closure|string|int|array|null $value - * @param \Closure|string|null $key - * @return static - */ - public function pluck($value, $key = null) - { - return $this->newInstance(Arr::pluck($this->items, $value, $key)); - } - - /** - * Run a map over each of the items. - * - * @template TMapValue - * - * @param callable(TValue, TKey): TMapValue $callback - * @return static - */ - public function map(callable $callback) - { - return $this->newInstance(Arr::map($this->items, $callback)); - } - - /** - * Run a dictionary map over the items. - * - * The callback should return an associative array with a single key/value pair. - * - * @template TMapToDictionaryKey of array-key - * @template TMapToDictionaryValue - * - * @param callable(TValue, TKey): array $callback - * @return static> - */ - public function mapToDictionary(callable $callback) - { - $dictionary = []; - - foreach ($this->items as $key => $item) { - $pair = $callback($item, $key); - - $key = key($pair); - - $value = reset($pair); - - if (! isset($dictionary[$key])) { - $dictionary[$key] = []; - } - - $dictionary[$key][] = $value; - } - - return $this->newInstance($dictionary); - } - - /** - * Run an associative map over each of the items. - * - * The callback should return an associative array with a single key/value pair. - * - * @template TMapWithKeysKey of array-key - * @template TMapWithKeysValue - * - * @param callable(TValue, TKey): array $callback - * @return static - */ - public function mapWithKeys(callable $callback) - { - return $this->newInstance(Arr::mapWithKeys($this->items, $callback)); - } - - /** - * Merge the collection with the given items. - * - * @template TMergeValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function merge($items) - { - return $this->newInstance(array_merge($this->items, $this->getArrayableItems($items))); - } - - /** - * Recursively merge the collection with the given items. - * - * @template TMergeRecursiveValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function mergeRecursive($items) - { - return $this->newInstance(array_merge_recursive($this->items, $this->getArrayableItems($items))); - } - - /** - * Multiply the items in the collection by the multiplier. - * - * @param int $multiplier - * @return static - */ - public function multiply(int $multiplier) - { - $new = $this->newInstance(); - - for ($i = 0; $i < $multiplier; $i++) { - $new->push(...$this->items); - } - - return $new; - } - - /** - * Create a collection by using this collection for keys and another for its values. - * - * @template TCombineValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @return static - */ - public function combine($values) - { - return $this->newInstance(array_combine($this->all(), $this->getArrayableItems($values))); - } - - /** - * Union the collection with the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function union($items) - { - return $this->newInstance($this->items + $this->getArrayableItems($items)); - } - - /** - * Create a new collection consisting of every n-th element. - * - * @param int $step - * @param int $offset - * @return ($step is positive-int ? static : never) - * - * @throws \InvalidArgumentException - */ - public function nth($step, $offset = 0) - { - if ($step < 1) { - throw new InvalidArgumentException('Step value must be at least 1.'); - } - - $new = []; - - $position = 0; - - foreach ($this->slice($offset)->items as $item) { - if ($position % $step === 0) { - $new[] = $item; - } - - $position++; - } - - return $this->newInstance($new); - } - - /** - * Get the items with the specified keys. - * - * @param \Illuminate\Support\Enumerable|array|string|null $keys - * @return static - */ - public function only($keys) - { - if (is_null($keys)) { - return $this->newInstance($this->items); - } - - if ($keys instanceof Enumerable) { - $keys = $keys->all(); - } - - $keys = is_array($keys) ? $keys : func_get_args(); - - return $this->newInstance(Arr::only($this->items, $keys)); - } - - /** - * Select specific values from the items within the collection. - * - * @param \Illuminate\Support\Enumerable|list|string|null $keys - * @return static - */ - public function select($keys) - { - if (is_null($keys)) { - return $this->newInstance($this->items); - } - - if ($keys instanceof Enumerable) { - $keys = $keys->all(); - } - - $keys = is_array($keys) ? $keys : func_get_args(); - - return $this->newInstance(Arr::select($this->items, $keys)); - } - - /** - * Get and remove the last N items from the collection. - * - * @param int $count - * @return ($count is 1 ? TValue|null : static) - */ - public function pop($count = 1) - { - if ($count < 1) { - return $this->newInstance(); - } - - if ($count === 1) { - return array_pop($this->items); - } - - if ($this->isEmpty()) { - return $this->newInstance(); - } - - $results = []; - - $collectionCount = $this->count(); - - foreach (range(1, min($count, $collectionCount)) as $item) { - $results[] = array_pop($this->items); - } - - return $this->newInstance($results); - } - - /** - * Push an item onto the beginning of the collection. - * - * @param TValue $value - * @param TKey $key - * @return $this - */ - public function prepend($value, $key = null) - { - $this->items = Arr::prepend($this->items, ...(func_num_args() > 1 ? func_get_args() : [$value])); - - return $this; - } - - /** - * Push one or more items onto the end of the collection. - * - * @param TValue ...$values - * @return $this - */ - public function push(...$values) - { - foreach ($values as $value) { - $this->items[] = $value; - } - - return $this; - } - - /** - * Prepend one or more items to the beginning of the collection. - * - * @param TValue ...$values - * @return $this - */ - public function unshift(...$values) - { - array_unshift($this->items, ...$values); - - return $this; - } - - /** - * Push all of the given items onto the collection. - * - * @template TConcatKey of array-key - * @template TConcatValue - * - * @param iterable $source - * @return static - */ - public function concat($source) - { - $result = $this->newInstance($this); - - foreach ($source as $item) { - $result->push($item); - } - - return $result; - } - - /** - * Get and remove an item from the collection. - * - * @template TPullDefault - * - * @param TKey $key - * @param TPullDefault|(\Closure(): TPullDefault) $default - * @return TValue|TPullDefault - */ - public function pull($key, $default = null) - { - return Arr::pull($this->items, $key, $default); - } - - /** - * Put an item in the collection by key. - * - * @param TKey $key - * @param TValue $value - * @return $this - */ - public function put($key, $value) - { - $this->offsetSet($key, $value); - - return $this; - } - - /** - * Get one or a specified number of items randomly from the collection. - * - * @param (callable(self): int)|int|null $number - * @param bool $preserveKeys - * @return ($number is null ? TValue : static) - * - * @throws \InvalidArgumentException - */ - public function random($number = null, $preserveKeys = false) - { - if (is_null($number)) { - return Arr::random($this->items); - } - - if (is_callable($number)) { - return $this->newInstance(Arr::random($this->items, $number($this), $preserveKeys)); - } - - return $this->newInstance(Arr::random($this->items, $number, $preserveKeys)); - } - - /** - * Replace the collection items with the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function replace($items) - { - return $this->newInstance(array_replace($this->items, $this->getArrayableItems($items))); - } - - /** - * Recursively replace the collection items with the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function replaceRecursive($items) - { - return $this->newInstance(array_replace_recursive($this->items, $this->getArrayableItems($items))); - } - - /** - * Reverse items order. - * - * @return static - */ - public function reverse() - { - return $this->newInstance(array_reverse($this->items, true)); - } - - /** - * Search the collection for a given value and return the corresponding key if successful. - * - * @param TValue|(callable(TValue,TKey): bool) $value - * @param bool $strict - * @return TKey|false - */ - public function search($value, $strict = false) - { - if (! $this->useAsCallable($value)) { - return array_search($value, $this->items, $strict); - } - - return array_find_key($this->items, $value) ?? false; - } - - /** - * Get the item before the given item. - * - * @param TValue|(callable(TValue,TKey): bool) $value - * @param bool $strict - * @return TValue|null - */ - public function before($value, $strict = false) - { - $key = $this->search($value, $strict); - - if ($key === false) { - return null; - } - - $position = ($keys = $this->keys())->search($key); - - if ($position === 0) { - return null; - } - - return $this->get($keys->get($position - 1)); - } - - /** - * Get the item after the given item. - * - * @param TValue|(callable(TValue,TKey): bool) $value - * @param bool $strict - * @return TValue|null - */ - public function after($value, $strict = false) - { - $key = $this->search($value, $strict); - - if ($key === false) { - return null; - } - - $position = ($keys = $this->keys())->search($key); - - if ($position === $keys->count() - 1) { - return null; - } - - return $this->get($keys->get($position + 1)); - } - - /** - * Get and remove the first N items from the collection. - * - * @param int<0, max> $count - * @return ($count is 1 ? TValue|null : static) - * - * @throws \InvalidArgumentException - */ - public function shift($count = 1) - { - if ($count < 0) { - throw new InvalidArgumentException('Number of shifted items may not be less than zero.'); - } - - if ($this->isEmpty()) { - return null; - } - - if ($count === 0) { - return $this->newInstance(); - } - - if ($count === 1) { - return array_shift($this->items); - } - - $results = []; - - $collectionCount = $this->count(); - - foreach (range(1, min($count, $collectionCount)) as $item) { - $results[] = array_shift($this->items); - } - - return $this->newInstance($results); - } - - /** - * Shuffle the items in the collection. - * - * @return static - */ - public function shuffle() - { - return $this->newInstance(Arr::shuffle($this->items)); - } - - /** - * Create chunks representing a "sliding window" view of the items in the collection. - * - * @param positive-int $size - * @param positive-int $step - * @return static - * - * @throws \InvalidArgumentException - */ - public function sliding($size = 2, $step = 1) - { - if ($size < 1) { - throw new InvalidArgumentException('Size value must be at least 1.'); - } elseif ($step < 1) { - throw new InvalidArgumentException('Step value must be at least 1.'); - } - - $chunks = floor(($this->count() - $size) / $step) + 1; - - return static::times($chunks, fn ($number) => $this->slice(($number - 1) * $step, $size)); - } - - /** - * Skip the first {$count} items. - * - * @param int $count - * @return static - */ - public function skip($count) - { - return $this->slice($count); - } - - /** - * Skip items in the collection until the given condition is met. - * - * @param TValue|callable(TValue,TKey): bool $value - * @return static - */ - public function skipUntil($value) - { - return $this->newInstance($this->lazy()->skipUntil($value)->all()); - } - - /** - * Skip items in the collection while the given condition is met. - * - * @param TValue|callable(TValue,TKey): bool $value - * @return static - */ - public function skipWhile($value) - { - return $this->newInstance($this->lazy()->skipWhile($value)->all()); - } - - /** - * Slice the underlying collection array. - * - * @param int $offset - * @param int|null $length - * @return static - */ - public function slice($offset, $length = null) - { - return $this->newInstance(array_slice($this->items, $offset, $length, true)); - } - - /** - * Split a collection into a certain number of groups. - * - * @param int $numberOfGroups - * @return ($numberOfGroups is positive-int ? static : never) - * - * @throws \InvalidArgumentException - */ - public function split($numberOfGroups) - { - if ($numberOfGroups < 1) { - throw new InvalidArgumentException('Number of groups must be at least 1.'); - } - - if ($this->isEmpty()) { - return $this->newInstance(); - } - - $groups = $this->newInstance(); - - $groupSize = floor($this->count() / $numberOfGroups); - - $remain = $this->count() % $numberOfGroups; - - $start = 0; - - for ($i = 0; $i < $numberOfGroups; $i++) { - $size = $groupSize; - - if ($i < $remain) { - $size++; - } - - if ($size) { - $groups->push($this->newInstance(array_slice($this->items, $start, $size))); - - $start += $size; - } - } - - return $groups; - } - - /** - * Split a collection into a certain number of groups, and fill the first groups completely. - * - * @param int $numberOfGroups - * @return ($numberOfGroups is positive-int ? static : never) - * - * @throws \InvalidArgumentException - */ - public function splitIn($numberOfGroups) - { - if ($numberOfGroups < 1) { - throw new InvalidArgumentException('Number of groups must be at least 1.'); - } - - return $this->chunk((int) ceil($this->count() / $numberOfGroups)); - } - - /** - * Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception. - * - * @param (callable(TValue, TKey): bool)|string|null $key - * @param mixed $operator - * @param mixed $value - * @return TValue - * - * @throws \Illuminate\Support\ItemNotFoundException - * @throws \Illuminate\Support\MultipleItemsFoundException - */ - public function sole($key = null, $operator = null, $value = null) - { - $filter = func_num_args() > 1 - ? $this->operatorForWhere(...func_get_args()) - : $key; - - $items = $this->unless($filter == null)->filter($filter); - - $count = $items->count(); - - if ($count === 0) { - throw new ItemNotFoundException; - } - - if ($count > 1) { - throw new MultipleItemsFoundException($count); - } - - return $items->first(); - } - - /** - * Determine if the collection contains a single item, optionally matching the given criteria. - * - * @param (callable(TValue, TKey): bool)|string|null $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function hasSole($key = null, $operator = null, $value = null): bool - { - $filter = func_num_args() > 1 - ? $this->operatorForWhere(...func_get_args()) - : $key; - - return $this - ->unless($filter == null) - ->filter($filter) - ->count() === 1; - } - - /** - * Get the first item in the collection but throw an exception if no matching items exist. - * - * @param (callable(TValue, TKey): bool)|string $key - * @param mixed $operator - * @param mixed $value - * @return TValue - * - * @throws \Illuminate\Support\ItemNotFoundException - */ - public function firstOrFail($key = null, $operator = null, $value = null) - { - $filter = func_num_args() > 1 - ? $this->operatorForWhere(...func_get_args()) - : $key; - - $placeholder = new stdClass(); - - $item = $this->first($filter, $placeholder); - - if ($item === $placeholder) { - throw new ItemNotFoundException; - } - - return $item; - } - - /** - * Chunk the collection into chunks of the given size. - * - * @param int $size - * @param bool $preserveKeys - * @return ($preserveKeys is true ? static : static>) - */ - public function chunk($size, $preserveKeys = true) - { - if ($size <= 0) { - return $this->newInstance(); - } - - $chunks = []; - - foreach (array_chunk($this->items, $size, $preserveKeys) as $chunk) { - $chunks[] = $this->newInstance($chunk); - } - - return $this->newInstance($chunks); - } - - /** - * Chunk the collection into chunks with a callback. - * - * @param callable(TValue, TKey, static): bool $callback - * @return static> - */ - public function chunkWhile(callable $callback) - { - return $this->newInstance( - $this->lazy()->chunkWhile($callback)->mapInto(static::class) - ); - } - - /** - * Sort through each item with a callback. - * - * @param (callable(TValue, TValue): int)|null|int $callback - * @return static - */ - public function sort($callback = null) - { - $items = $this->items; - - $callback && is_callable($callback) - ? uasort($items, $callback) - : asort($items, $callback ?? SORT_REGULAR); - - return $this->newInstance($items); - } - - /** - * Sort items in descending order. - * - * @param int-mask-of $options - * @return static - */ - public function sortDesc($options = SORT_REGULAR) - { - $items = $this->items; - - arsort($items, $options); - - return $this->newInstance($items); - } - - /** - * Sort the collection using the given callback. - * - * @param array|(callable(TValue, TKey): mixed)|string|int $callback - * @param int-mask-of $options - * @param SortDirection|bool $descending - * @return static - */ - public function sortBy($callback, $options = SORT_REGULAR, $descending = false) - { - if (is_array($callback) && ! is_callable($callback)) { - return $this->sortByMany($callback, $options); - } - - $results = []; - - $callback = $this->valueRetriever($callback); - - // First we will loop through the items and get the comparator from a callback - // function which we were given. Then, we will sort the returned values and - // grab all the corresponding values for the sorted keys from this array. - foreach ($this->items as $key => $value) { - $results[$key] = $callback($value, $key); - } - - match ($descending) { - false, SortDirection::Ascending => asort($results, $options), - true, SortDirection::Descending => arsort($results, $options), - }; - - // Once we have sorted all of the keys in the array, we will loop through them - // and grab the corresponding model so we can set the underlying items list - // to the sorted version. Then we'll just return the collection instance. - foreach (array_keys($results) as $key) { - $results[$key] = $this->items[$key]; - } - - return $this->newInstance($results); - } - - /** - * Sort the collection using multiple comparisons. - * - * @param array $comparisons - * @param int-mask-of $options - * @return static - */ - protected function sortByMany(array $comparisons = [], int $options = SORT_REGULAR) - { - $items = $this->items; - - uasort($items, function ($a, $b) use ($comparisons, $options) { - foreach ($comparisons as $comparison) { - $comparison = Arr::wrap($comparison); - - $prop = $comparison[0]; - - $direction = match (Arr::get($comparison, 1, true)) { - true, 'asc', SortDirection::Ascending => SortDirection::Ascending, - false, 'desc', SortDirection::Descending => SortDirection::Descending, - default => SortDirection::Descending, // for backwards compatibility - }; - - if (! is_string($prop) && is_callable($prop)) { - $result = $prop($a, $b); - } else { - $values = [data_get($a, $prop), data_get($b, $prop)]; - - if ($direction === SortDirection::Descending) { - $values = array_reverse($values); - } - - if (($options & SORT_FLAG_CASE) === SORT_FLAG_CASE) { - if (($options & SORT_NATURAL) === SORT_NATURAL) { - $result = strnatcasecmp($values[0], $values[1]); - } else { - $result = strcasecmp($values[0], $values[1]); - } - } else { - $result = match ($options) { - SORT_NUMERIC => (int) $values[0] <=> (int) $values[1], - SORT_STRING => strcmp($values[0], $values[1]), - SORT_NATURAL => strnatcmp((string) $values[0], (string) $values[1]), - SORT_LOCALE_STRING => strcoll($values[0], $values[1]), - default => $values[0] <=> $values[1], - }; - } - } - - if ($result === 0) { - continue; - } - - return $result; - } - }); - - return $this->newInstance($items); - } - - /** - * Sort the collection in descending order using the given callback. - * - * @param array|(callable(TValue, TKey): mixed)|string|int $callback - * @param int-mask-of $options - * @return static - */ - public function sortByDesc($callback, $options = SORT_REGULAR) - { - if (is_array($callback) && ! is_callable($callback)) { - foreach ($callback as $index => $key) { - $comparison = Arr::wrap($key); - - $comparison[1] = SortDirection::Descending; - - $callback[$index] = $comparison; - } - } - - return $this->sortBy($callback, $options, true); - } - - /** - * Sort the collection keys. - * - * @param int-mask-of $options - * @param SortDirection|bool $descending - * @return static - */ - public function sortKeys($options = SORT_REGULAR, $descending = false) - { - $items = $this->items; - - match ($descending) { - false, SortDirection::Ascending => ksort($items, $options), - true, SortDirection::Descending => krsort($items, $options), - }; - - return $this->newInstance($items); - } - - /** - * Sort the collection keys in descending order. - * - * @param int-mask-of $options - * @return static - */ - public function sortKeysDesc($options = SORT_REGULAR) - { - return $this->sortKeys($options, SortDirection::Descending); - } - - /** - * Sort the collection keys using a callback. - * - * @param callable(TKey, TKey): int $callback - * @return static - */ - public function sortKeysUsing(callable $callback) - { - $items = $this->items; - - uksort($items, $callback); - - return $this->newInstance($items); - } - - /** - * Splice a portion of the underlying collection array. - * - * @param int $offset - * @param int|null $length - * @param array $replacement - * @return static - */ - public function splice($offset, $length = null, $replacement = []) - { - if (func_num_args() === 1) { - return $this->newInstance(array_splice($this->items, $offset)); - } - - return $this->newInstance(array_splice($this->items, $offset, $length, $this->getArrayableItems($replacement))); - } - - /** - * Take the first or last {$limit} items. - * - * @param int $limit - * @return static - */ - public function take($limit) - { - if ($limit < 0) { - return $this->slice($limit, abs($limit)); - } - - return $this->slice(0, $limit); - } - - /** - * Take items in the collection until the given condition is met. - * - * @param TValue|callable(TValue,TKey): bool $value - * @return static - */ - public function takeUntil($value) - { - return $this->newInstance($this->lazy()->takeUntil($value)->all()); - } - - /** - * Take items in the collection while the given condition is met. - * - * @param TValue|callable(TValue,TKey): bool $value - * @return static - */ - public function takeWhile($value) - { - return $this->newInstance($this->lazy()->takeWhile($value)->all()); - } - - /** - * Transform each item in the collection using a callback. - * - * @template TMapValue - * - * @param callable(TValue, TKey): TMapValue $callback - * @return $this - * - * @phpstan-this-out static - */ - public function transform(callable $callback) - { - $this->items = $this->map($callback)->all(); - - return $this; - } - - /** - * Flatten a multi-dimensional associative array with dots. - * - * @param int $depth - * @return static - */ - public function dot($depth = INF) - { - return $this->newInstance(Arr::dot($this->all(), '', $depth)); - } - - /** - * Convert a flatten "dot" notation array into an expanded array. - * - * @return static - */ - public function undot() - { - return $this->newInstance(Arr::undot($this->all())); - } - - /** - * Return only unique items from the collection array. - * - * @param (callable(TValue, TKey): mixed)|string|null $key - * @param bool $strict - * @return static - */ - public function unique($key = null, $strict = false) - { - if (is_null($key) && $strict === false) { - return $this->newInstance(array_unique($this->items, SORT_REGULAR)); - } - - $callback = $this->valueRetriever($key); - - $exists = []; - - return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) { - if (in_array($id = $callback($item, $key), $exists, $strict)) { - return true; - } - - $exists[] = $id; - }); - } - - /** - * Reset the keys on the underlying array. - * - * @return static - */ - public function values() - { - return $this->newInstance(array_values($this->items)); - } - - /** - * Zip the collection together with one or more arrays. - * - * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]); - * => [[1, 4], [2, 5], [3, 6]] - * - * @template TZipValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable ...$items - * @return static> - */ - public function zip($items) - { - $arrayableItems = array_map(fn ($items) => $this->getArrayableItems($items), func_get_args()); - - $params = array_merge([fn () => $this->newInstance(func_get_args()), $this->items], $arrayableItems); - - return $this->newInstance(array_map(...$params)); - } - - /** - * Pad collection to the specified length with a value. - * - * @template TPadValue - * - * @param int $size - * @param TPadValue $value - * @return static - */ - public function pad($size, $value) - { - return $this->newInstance(array_pad($this->items, $size, $value)); - } - - /** - * Get an iterator for the items. - * - * @return \ArrayIterator - */ - public function getIterator(): Traversable - { - return new ArrayIterator($this->items); - } - - /** - * Count the number of items in the collection. - * - * @return int<0, max> - */ - public function count(): int - { - return count($this->items); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function countBy($countBy = null) - { - return $this->newInstance($this->lazy()->countBy($countBy)->all()); - } - - /** - * Add an item to the collection. - * - * @param TValue $item - * @return $this - */ - public function add($item) - { - $this->items[] = $item; - - return $this; - } - - /** - * Get a base Support collection instance from this collection. - * - * @return \Illuminate\Support\Collection - */ - public function toBase() - { - return new self($this); - } - - /** - * Determine if an item exists at an offset. - * - * @param TKey $offset - * @return bool - */ - public function offsetExists($offset): bool - { - return isset($this->items[$offset]); - } - - /** - * Get an item at a given offset. - * - * @param TKey $offset - * @return TValue - */ - public function offsetGet($offset): mixed - { - return $this->items[$offset]; - } - - /** - * Set the item at a given offset. - * - * @param TKey|null $offset - * @param TValue $value - * @return void - */ - public function offsetSet($offset, $value): void - { - if (is_null($offset)) { - $this->items[] = $value; - } else { - $this->items[$offset] = $value; - } - } - - /** - * Unset the item at a given offset. - * - * @param TKey $offset - * @return void - */ - public function offsetUnset($offset): void - { - unset($this->items[$offset]); - } -} diff --git a/src/Illuminate/Support/Enumerable.php b/src/Illuminate/Support/Enumerable.php deleted file mode 100644 index 36e047050..000000000 --- a/src/Illuminate/Support/Enumerable.php +++ /dev/null @@ -1,1379 +0,0 @@ - - * @extends \IteratorAggregate - */ -interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable -{ - /** - * Create a new collection instance if the value isn't one already. - * - * @template TMakeKey of array-key - * @template TMakeValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable|null $items - * @return static - */ - public static function make($items = []); - - /** - * Create a new instance by invoking the callback a given amount of times. - * - * @template TTimesValue - * - * @param int $number - * @param (callable(int): TTimesValue)|null $callback - * @return static - */ - public static function times($number, ?callable $callback = null); - - /** - * Create a collection with the given range. - * - * @param int $from - * @param int $to - * @param int $step - * @return static - */ - public static function range($from, $to, $step = 1); - - /** - * Wrap the given value in a collection if applicable. - * - * @template TWrapValue - * - * @param iterable|TWrapValue $value - * @return static - */ - public static function wrap($value); - - /** - * Get the underlying items from the given collection if applicable. - * - * @template TUnwrapKey of array-key - * @template TUnwrapValue - * - * @param array|static $value - * @return array - */ - public static function unwrap($value); - - /** - * Create a new instance with no items. - * - * @return static - */ - public static function empty(); - - /** - * Get all items in the enumerable. - * - * @return array - */ - public function all(); - - /** - * Alias for the "avg" method. - * - * @param (callable(TValue): float|int)|string|null $callback - * @return float|int|null - */ - public function average($callback = null); - - /** - * Get the median of a given key. - * - * @param string|array|null $key - * @return float|int|null - */ - public function median($key = null); - - /** - * Get the mode of a given key. - * - * @param string|array|null $key - * @return array|null - */ - public function mode($key = null); - - /** - * Collapse the items into a single enumerable. - * - * @return static - */ - public function collapse(); - - /** - * Alias for the "contains" method. - * - * @param (callable(TValue, TKey): bool)|TValue|string $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function some($key, $operator = null, $value = null); - - /** - * Determine if an item exists, using strict comparison. - * - * @param (callable(TValue): bool)|TValue|array-key $key - * @param TValue|null $value - * @return bool - */ - public function containsStrict($key, $value = null); - - /** - * Get the average value of a given key. - * - * @param (callable(TValue): float|int)|string|null $callback - * @return float|int|null - */ - public function avg($callback = null); - - /** - * Determine if an item exists in the enumerable. - * - * @param (callable(TValue, TKey): bool)|TValue|string $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function contains($key, $operator = null, $value = null); - - /** - * Determine if an item is not contained in the collection. - * - * @param mixed $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function doesntContain($key, $operator = null, $value = null); - - /** - * Cross join with the given lists, returning all possible permutations. - * - * @template TCrossJoinKey - * @template TCrossJoinValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable ...$lists - * @return static> - */ - public function crossJoin(...$lists); - - /** - * Dump the collection and end the script. - * - * @param mixed ...$args - * @return never - */ - public function dd(...$args); - - /** - * Dump the collection. - * - * @param mixed ...$args - * @return $this - */ - public function dump(...$args); - - /** - * Get the items that are not present in the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function diff($items); - - /** - * Get the items that are not present in the given items, using the callback. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @param callable(TValue, TValue): int $callback - * @return static - */ - public function diffUsing($items, callable $callback); - - /** - * Get the items whose keys and values are not present in the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function diffAssoc($items); - - /** - * Get the items whose keys and values are not present in the given items, using the callback. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @param callable(TKey, TKey): int $callback - * @return static - */ - public function diffAssocUsing($items, callable $callback); - - /** - * Get the items whose keys are not present in the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function diffKeys($items); - - /** - * Get the items whose keys are not present in the given items, using the callback. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @param callable(TKey, TKey): int $callback - * @return static - */ - public function diffKeysUsing($items, callable $callback); - - /** - * Retrieve duplicate items. - * - * @param (callable(TValue): bool)|string|null $callback - * @param bool $strict - * @return static - */ - public function duplicates($callback = null, $strict = false); - - /** - * Retrieve duplicate items using strict comparison. - * - * @param (callable(TValue): bool)|string|null $callback - * @return static - */ - public function duplicatesStrict($callback = null); - - /** - * Execute a callback over each item. - * - * @param callable(TValue, TKey): mixed $callback - * @return $this - */ - public function each(callable $callback); - - /** - * Execute a callback over each nested chunk of items. - * - * @param callable $callback - * @return static - */ - public function eachSpread(callable $callback); - - /** - * Determine if all items pass the given truth test. - * - * @param (callable(TValue, TKey): bool)|TValue|string $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function every($key, $operator = null, $value = null); - - /** - * Get all items except for those with the specified keys. - * - * @param \Illuminate\Support\Enumerable|array $keys - * @return static - */ - public function except($keys); - - /** - * Run a filter over each of the items. - * - * @param (callable(TValue): bool)|null $callback - * @return static - */ - public function filter(?callable $callback = null); - - /** - * Apply the callback if the given "value" is (or resolves to) truthy. - * - * @template TWhenReturnType as null - * - * @param bool $value - * @param (callable($this): TWhenReturnType)|null $callback - * @param (callable($this): TWhenReturnType)|null $default - * @return $this|TWhenReturnType - */ - public function when($value, ?callable $callback = null, ?callable $default = null); - - /** - * Apply the callback if the collection is empty. - * - * @template TWhenEmptyReturnType - * - * @param (callable($this): TWhenEmptyReturnType) $callback - * @param (callable($this): TWhenEmptyReturnType)|null $default - * @return $this|TWhenEmptyReturnType - */ - public function whenEmpty(callable $callback, ?callable $default = null); - - /** - * Apply the callback if the collection is not empty. - * - * @template TWhenNotEmptyReturnType - * - * @param callable($this): TWhenNotEmptyReturnType $callback - * @param (callable($this): TWhenNotEmptyReturnType)|null $default - * @return $this|TWhenNotEmptyReturnType - */ - public function whenNotEmpty(callable $callback, ?callable $default = null); - - /** - * Apply the callback if the given "value" is (or resolves to) falsy. - * - * @template TUnlessReturnType - * - * @param bool $value - * @param (callable($this): TUnlessReturnType) $callback - * @param (callable($this): TUnlessReturnType)|null $default - * @return $this|TUnlessReturnType - */ - public function unless($value, callable $callback, ?callable $default = null); - - /** - * Apply the callback unless the collection is empty. - * - * @template TUnlessEmptyReturnType - * - * @param callable($this): TUnlessEmptyReturnType $callback - * @param (callable($this): TUnlessEmptyReturnType)|null $default - * @return $this|TUnlessEmptyReturnType - */ - public function unlessEmpty(callable $callback, ?callable $default = null); - - /** - * Apply the callback unless the collection is not empty. - * - * @template TUnlessNotEmptyReturnType - * - * @param callable($this): TUnlessNotEmptyReturnType $callback - * @param (callable($this): TUnlessNotEmptyReturnType)|null $default - * @return $this|TUnlessNotEmptyReturnType - */ - public function unlessNotEmpty(callable $callback, ?callable $default = null); - - /** - * Filter items by the given key value pair. - * - * @param string $key - * @param mixed $operator - * @param mixed $value - * @return static - */ - public function where($key, $operator = null, $value = null); - - /** - * Filter items where the value for the given key is null. - * - * @param string|null $key - * @return static - */ - public function whereNull($key = null); - - /** - * Filter items where the value for the given key is not null. - * - * @param string|null $key - * @return static - */ - public function whereNotNull($key = null); - - /** - * Filter items by the given key value pair using strict comparison. - * - * @param string $key - * @param mixed $value - * @return static - */ - public function whereStrict($key, $value); - - /** - * Filter items by the given key value pair. - * - * @param string $key - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @param bool $strict - * @return static - */ - public function whereIn($key, $values, $strict = false); - - /** - * Filter items by the given key value pair using strict comparison. - * - * @param string $key - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @return static - */ - public function whereInStrict($key, $values); - - /** - * Filter items such that the value of the given key is between the given values. - * - * @param string $key - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @return static - */ - public function whereBetween($key, $values); - - /** - * Filter items such that the value of the given key is not between the given values. - * - * @param string $key - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @return static - */ - public function whereNotBetween($key, $values); - - /** - * Filter items by the given key value pair. - * - * @param string $key - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @param bool $strict - * @return static - */ - public function whereNotIn($key, $values, $strict = false); - - /** - * Filter items by the given key value pair using strict comparison. - * - * @param string $key - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @return static - */ - public function whereNotInStrict($key, $values); - - /** - * Filter the items, removing any items that don't match the given type(s). - * - * @template TWhereInstanceOf - * - * @param class-string|array> $type - * @return static - */ - public function whereInstanceOf($type); - - /** - * Get the first item from the enumerable passing the given truth test. - * - * @template TFirstDefault - * - * @param (callable(TValue,TKey): bool)|null $callback - * @param TFirstDefault|(\Closure(): TFirstDefault) $default - * @return TValue|TFirstDefault - */ - public function first(?callable $callback = null, $default = null); - - /** - * Get the first item by the given key value pair. - * - * @param string $key - * @param mixed $operator - * @param mixed $value - * @return TValue|null - */ - public function firstWhere($key, $operator = null, $value = null); - - /** - * Get a flattened array of the items in the collection. - * - * @param int $depth - * @return static - */ - public function flatten($depth = INF); - - /** - * Flip the values with their keys. - * - * @return static - */ - public function flip(); - - /** - * Get an item from the collection by key. - * - * @template TGetDefault - * - * @param TKey $key - * @param TGetDefault|(\Closure(): TGetDefault) $default - * @return TValue|TGetDefault - */ - public function get($key, $default = null); - - /** - * Group an associative array by a field or using a callback. - * - * @template TGroupKey of array-key|\UnitEnum|\Stringable - * - * @param (callable(TValue, TKey): TGroupKey)|array|string $groupBy - * @param bool $preserveKeys - * @return static< - * ($groupBy is (array|string) - * ? array-key - * : (TGroupKey is \UnitEnum ? array-key : (TGroupKey is \Stringable ? string : TGroupKey))), - * static<($preserveKeys is true ? TKey : int), ($groupBy is array ? mixed : TValue)> - * > - */ - public function groupBy($groupBy, $preserveKeys = false); - - /** - * Key an associative array by a field or using a callback. - * - * @template TNewKey of array-key|\UnitEnum - * - * @param (callable(TValue, TKey): TNewKey)|array|string $keyBy - * @return static<($keyBy is (array|string) ? array-key : (TNewKey is \UnitEnum ? array-key : TNewKey)), TValue> - */ - public function keyBy($keyBy); - - /** - * Determine if an item exists in the collection by key. - * - * @param TKey|array $key - * @return bool - */ - public function has($key); - - /** - * Determine if any of the keys exist in the collection. - * - * @param mixed $key - * @return bool - */ - public function hasAny($key); - - /** - * Concatenate values of a given key as a string. - * - * @param (callable(TValue, TKey): mixed)|string $value - * @param string|null $glue - * @return string - */ - public function implode($value, $glue = null); - - /** - * Intersect the collection with the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function intersect($items); - - /** - * Intersect the collection with the given items, using the callback. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @param callable(TValue, TValue): int $callback - * @return static - */ - public function intersectUsing($items, callable $callback); - - /** - * Intersect the collection with the given items with additional index check. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function intersectAssoc($items); - - /** - * Intersect the collection with the given items with additional index check, using the callback. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @param callable(TValue, TValue): int $callback - * @return static - */ - public function intersectAssocUsing($items, callable $callback); - - /** - * Intersect the collection with the given items by key. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function intersectByKeys($items); - - /** - * Determine if the collection is empty or not. - * - * @return bool - */ - public function isEmpty(); - - /** - * Determine if the collection is not empty. - * - * @return bool - */ - public function isNotEmpty(); - - /** - * Determine if the collection contains a single item. - * - * @return bool - */ - public function containsOneItem(); - - /** - * Determine if the collection contains multiple items. - * - * @return bool - */ - public function containsManyItems(); - - /** - * Determine if the collection contains a single item, optionally matching the given criteria. - * - * @param (callable(TValue, TKey): bool)|string|null $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function hasSole($key = null, $operator = null, $value = null); - - /** - * Determine if the collection contains multiple items, optionally matching the given criteria. - * - * @param (callable(TValue, TKey): bool)|string|null $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function hasMany($key = null, $operator = null, $value = null); - - /** - * Join all items from the collection using a string. The final items can use a separate glue string. - * - * @param string $glue - * @param string $finalGlue - * @return string - */ - public function join($glue, $finalGlue = ''); - - /** - * Get the keys of the collection items. - * - * @return static - */ - public function keys(); - - /** - * Get the last item from the collection. - * - * @template TLastDefault - * - * @param (callable(TValue, TKey): bool)|null $callback - * @param TLastDefault|(\Closure(): TLastDefault) $default - * @return TValue|TLastDefault - */ - public function last(?callable $callback = null, $default = null); - - /** - * Run a map over each of the items. - * - * @template TMapValue - * - * @param callable(TValue, TKey): TMapValue $callback - * @return static - */ - public function map(callable $callback); - - /** - * Run a map over each nested chunk of items. - * - * @param callable $callback - * @return static - */ - public function mapSpread(callable $callback); - - /** - * Run a dictionary map over the items. - * - * The callback should return an associative array with a single key/value pair. - * - * @template TMapToDictionaryKey of array-key - * @template TMapToDictionaryValue - * - * @param callable(TValue, TKey): array $callback - * @return static> - */ - public function mapToDictionary(callable $callback); - - /** - * Run a grouping map over the items. - * - * The callback should return an associative array with a single key/value pair. - * - * @template TMapToGroupsKey of array-key - * @template TMapToGroupsValue - * - * @param callable(TValue, TKey): array $callback - * @return static> - */ - public function mapToGroups(callable $callback); - - /** - * Run an associative map over each of the items. - * - * The callback should return an associative array with a single key/value pair. - * - * @template TMapWithKeysKey of array-key - * @template TMapWithKeysValue - * - * @param callable(TValue, TKey): array $callback - * @return static - */ - public function mapWithKeys(callable $callback); - - /** - * Map a collection and flatten the result by a single level. - * - * @template TFlatMapKey of array-key - * @template TFlatMapValue - * - * @param callable(TValue, TKey): (\Illuminate\Support\Collection|array) $callback - * @return static - */ - public function flatMap(callable $callback); - - /** - * Map the values into a new class. - * - * @template TMapIntoValue - * - * @param class-string $class - * @return static - */ - public function mapInto($class); - - /** - * Merge the collection with the given items. - * - * @template TMergeValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function merge($items); - - /** - * Recursively merge the collection with the given items. - * - * @template TMergeRecursiveValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function mergeRecursive($items); - - /** - * Create a collection by using this collection for keys and another for its values. - * - * @template TCombineValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @return static - */ - public function combine($values); - - /** - * Union the collection with the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function union($items); - - /** - * Get the min value of a given key. - * - * @template TMinResult = mixed - * - * @param (callable(TValue): TMinResult)|string|null $callback - * @return ($callback is callable ? ?TMinResult : ($callback is null ? ?TValue : mixed)) - */ - public function min($callback = null); - - /** - * Get the max value of a given key. - * - * @template TMaxResult = mixed - * - * @param (callable(TValue): TMaxResult)|string|null $callback - * @return ($callback is callable ? ?TMaxResult : ($callback is null ? ?TValue : mixed)) - */ - public function max($callback = null); - - /** - * Create a new collection consisting of every n-th element. - * - * @param int $step - * @param int $offset - * @return static - */ - public function nth($step, $offset = 0); - - /** - * Get the items with the specified keys. - * - * @param \Illuminate\Support\Enumerable|array|string $keys - * @return static - */ - public function only($keys); - - /** - * "Paginate" the collection by slicing it into a smaller collection. - * - * @param int $page - * @param int $perPage - * @return static - */ - public function forPage($page, $perPage); - - /** - * Partition the collection into two arrays using the given callback or key. - * - * @param (callable(TValue, TKey): bool)|TValue|string $key - * @param mixed $operator - * @param mixed $value - * @return static, static> - */ - public function partition($key, $operator = null, $value = null); - - /** - * Push all of the given items onto the collection. - * - * @template TConcatKey of array-key - * @template TConcatValue - * - * @param iterable $source - * @return static - */ - public function concat($source); - - /** - * Get one or a specified number of items randomly from the collection. - * - * @param int|null $number - * @return ($number is null ? TValue : static) - * - * @throws \InvalidArgumentException - */ - public function random($number = null); - - /** - * Reduce the collection to a single value. - * - * @template TReduceInitial - * @template TReduceReturnType - * - * @param callable(TReduceInitial|TReduceReturnType, TValue, TKey): TReduceReturnType $callback - * @param TReduceInitial $initial - * @return TReduceInitial|TReduceReturnType - */ - public function reduce(callable $callback, $initial = null); - - /** - * Reduce the collection to a single value by mutating an initial value. - * - * @template TReduceIntoInitial - * - * @param TReduceIntoInitial $initial - * @param callable(TReduceIntoInitial, TValue, TKey): void $callback - * @return TReduceIntoInitial - */ - public function reduceInto($initial, callable $callback); - - /** - * Reduce the collection to multiple aggregate values. - * - * @param callable $callback - * @param mixed ...$initial - * @return array - * - * @throws \UnexpectedValueException - */ - public function reduceSpread(callable $callback, ...$initial); - - /** - * Replace the collection items with the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function replace($items); - - /** - * Recursively replace the collection items with the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function replaceRecursive($items); - - /** - * Reverse items order. - * - * @return static - */ - public function reverse(); - - /** - * Search the collection for a given value and return the corresponding key if successful. - * - * @param TValue|callable(TValue,TKey): bool $value - * @param bool $strict - * @return TKey|false - */ - public function search($value, $strict = false); - - /** - * Get the item before the given item. - * - * @param TValue|(callable(TValue,TKey): bool) $value - * @param bool $strict - * @return TValue|null - */ - public function before($value, $strict = false); - - /** - * Get the item after the given item. - * - * @param TValue|(callable(TValue,TKey): bool) $value - * @param bool $strict - * @return TValue|null - */ - public function after($value, $strict = false); - - /** - * Shuffle the items in the collection. - * - * @return static - */ - public function shuffle(); - - /** - * Create chunks representing a "sliding window" view of the items in the collection. - * - * @param int $size - * @param int $step - * @return static - */ - public function sliding($size = 2, $step = 1); - - /** - * Skip the first {$count} items. - * - * @param int $count - * @return static - */ - public function skip($count); - - /** - * Skip items in the collection until the given condition is met. - * - * @param TValue|callable(TValue,TKey): bool $value - * @return static - */ - public function skipUntil($value); - - /** - * Skip items in the collection while the given condition is met. - * - * @param TValue|callable(TValue,TKey): bool $value - * @return static - */ - public function skipWhile($value); - - /** - * Get a slice of items from the enumerable. - * - * @param int $offset - * @param int|null $length - * @return static - */ - public function slice($offset, $length = null); - - /** - * Split a collection into a certain number of groups. - * - * @param int $numberOfGroups - * @return static - */ - public function split($numberOfGroups); - - /** - * Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception. - * - * @param (callable(TValue, TKey): bool)|string $key - * @param mixed $operator - * @param mixed $value - * @return TValue - * - * @throws \Illuminate\Support\ItemNotFoundException - * @throws \Illuminate\Support\MultipleItemsFoundException - */ - public function sole($key = null, $operator = null, $value = null); - - /** - * Get the first item in the collection but throw an exception if no matching items exist. - * - * @param (callable(TValue, TKey): bool)|string|null $key - * @param mixed $operator - * @param mixed $value - * @return TValue - * - * @throws \Illuminate\Support\ItemNotFoundException - */ - public function firstOrFail($key = null, $operator = null, $value = null); - - /** - * Chunk the collection into chunks of the given size. - * - * @param int $size - * @return static - */ - public function chunk($size); - - /** - * Chunk the collection into chunks with a callback. - * - * @param callable(TValue, TKey, static): bool $callback - * @return static> - */ - public function chunkWhile(callable $callback); - - /** - * Chunk the collection into chunks by comparing adjacent values using the given key or callback. - * - * @param (callable(TValue, TKey): mixed)|string $key - * @return static> - */ - public function chunkBy($key); - - /** - * Split a collection into a certain number of groups, and fill the first groups completely. - * - * @param int $numberOfGroups - * @return static - */ - public function splitIn($numberOfGroups); - - /** - * Sort through each item with a callback. - * - * @param (callable(TValue, TValue): int)|null|int $callback - * @return static - */ - public function sort($callback = null); - - /** - * Sort items in descending order. - * - * @param int-mask-of $options - * @return static - */ - public function sortDesc($options = SORT_REGULAR); - - /** - * Sort the collection using the given callback. - * - * @param array|(callable(TValue, TKey): mixed)|string|int $callback - * @param int-mask-of $options - * @param bool $descending - * @return static - */ - public function sortBy($callback, $options = SORT_REGULAR, $descending = false); - - /** - * Sort the collection in descending order using the given callback. - * - * @param array|(callable(TValue, TKey): mixed)|string|int $callback - * @param int-mask-of $options - * @return static - */ - public function sortByDesc($callback, $options = SORT_REGULAR); - - /** - * Sort the collection keys. - * - * @param int-mask-of $options - * @param bool $descending - * @return static - */ - public function sortKeys($options = SORT_REGULAR, $descending = false); - - /** - * Sort the collection keys in descending order. - * - * @param int-mask-of $options - * @return static - */ - public function sortKeysDesc($options = SORT_REGULAR); - - /** - * Sort the collection keys using a callback. - * - * @param callable(TKey, TKey): int $callback - * @return static - */ - public function sortKeysUsing(callable $callback); - - /** - * Get the sum of the given values. - * - * @param (callable(TValue, TKey): mixed)|string|null $callback - * @return mixed - */ - public function sum($callback = null); - - /** - * Take the first or last {$limit} items. - * - * @param int $limit - * @return static - */ - public function take($limit); - - /** - * Take items in the collection until the given condition is met. - * - * @param TValue|callable(TValue,TKey): bool $value - * @return static - */ - public function takeUntil($value); - - /** - * Take items in the collection while the given condition is met. - * - * @param TValue|callable(TValue,TKey): bool $value - * @return static - */ - public function takeWhile($value); - - /** - * Pass the collection to the given callback and then return it. - * - * @param callable(TValue): mixed $callback - * @return $this - */ - public function tap(callable $callback); - - /** - * Pass the enumerable to the given callback and return the result. - * - * @template TPipeReturnType - * - * @param callable($this): TPipeReturnType $callback - * @return TPipeReturnType - */ - public function pipe(callable $callback); - - /** - * Pass the collection into a new class. - * - * @template TPipeIntoValue - * - * @param class-string $class - * @return TPipeIntoValue - */ - public function pipeInto($class); - - /** - * Pass the collection through a series of callable pipes and return the result. - * - * @param array $pipes - * @return mixed - */ - public function pipeThrough($pipes); - - /** - * Get the values of a given key. - * - * @param string|array $value - * @param string|null $key - * @return static - */ - public function pluck($value, $key = null); - - /** - * Create a collection of all elements that do not pass a given truth test. - * - * @param (callable(TValue, TKey): bool)|bool|TValue $callback - * @return static - */ - public function reject($callback = true); - - /** - * Convert a flatten "dot" notation array into an expanded array. - * - * @return static - */ - public function undot(); - - /** - * Return only unique items from the collection array. - * - * @param (callable(TValue, TKey): mixed)|string|null $key - * @param bool $strict - * @return static - */ - public function unique($key = null, $strict = false); - - /** - * Return only unique items from the collection array using strict comparison. - * - * @param (callable(TValue, TKey): mixed)|string|null $key - * @return static - */ - public function uniqueStrict($key = null); - - /** - * Reset the keys on the underlying array. - * - * @return static - */ - public function values(); - - /** - * Pad collection to the specified length with a value. - * - * @template TPadValue - * - * @param int $size - * @param TPadValue $value - * @return static - */ - public function pad($size, $value); - - /** - * Get the values iterator. - * - * @return \Traversable - */ - public function getIterator(): Traversable; - - /** - * Count the number of items in the collection. - * - * @return int - */ - public function count(): int; - - /** - * Count the number of items in the collection by a field or using a callback. - * - * @param (callable(TValue, TKey): (array-key|\UnitEnum))|string|null $countBy - * @return static - */ - public function countBy($countBy = null); - - /** - * Zip the collection together with one or more arrays. - * - * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]); - * => [[1, 4], [2, 5], [3, 6]] - * - * @template TZipValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable ...$items - * @return static> - */ - public function zip($items); - - /** - * Collect the values into a collection. - * - * @return \Illuminate\Support\Collection - */ - public function collect(); - - /** - * Get the collection of items as a plain array. - * - * @return array - */ - public function toArray(); - - /** - * Convert the object into something JSON serializable. - * - * @return mixed - */ - public function jsonSerialize(): mixed; - - /** - * Get the collection of items as JSON. - * - * @param int $options - * @return string - */ - public function toJson($options = 0); - - /** - * Get the collection of items as pretty print formatted JSON. - * - * @param int $options - * @return string - */ - public function toPrettyJson(int $options = 0); - - /** - * Get a CachingIterator instance. - * - * @param int $flags - * @return \CachingIterator - */ - public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING); - - /** - * Convert the collection to its string representation. - * - * @return string - */ - public function __toString(); - - /** - * Indicate that the model's string representation should be escaped when __toString is invoked. - * - * @param bool $escape - * @return $this - */ - public function escapeWhenCastingToString($escape = true); - - /** - * Add a method to the list of proxied methods. - * - * @param string $method - * @return void - */ - public static function proxy($method); - - /** - * Dynamically access collection proxies. - * - * @param string $key - * @return mixed - * - * @throws \Exception - */ - public function __get($key); -} diff --git a/src/Illuminate/Support/HigherOrderCollectionProxy.php b/src/Illuminate/Support/HigherOrderCollectionProxy.php deleted file mode 100644 index 035d0fda4..000000000 --- a/src/Illuminate/Support/HigherOrderCollectionProxy.php +++ /dev/null @@ -1,69 +0,0 @@ - - * @mixin TValue - */ -class HigherOrderCollectionProxy -{ - /** - * The collection being operated on. - * - * @var \Illuminate\Support\Enumerable - */ - protected $collection; - - /** - * The method being proxied. - * - * @var string - */ - protected $method; - - /** - * Create a new proxy instance. - * - * @param \Illuminate\Support\Enumerable $collection - * @param string $method - */ - public function __construct(Enumerable $collection, $method) - { - $this->method = $method; - $this->collection = $collection; - } - - /** - * Proxy accessing an attribute onto the collection items. - * - * @param string $key - * @return mixed - */ - public function __get($key) - { - return $this->collection->{$this->method}(function ($value) use ($key) { - return is_array($value) ? $value[$key] : $value->{$key}; - }); - } - - /** - * Proxy a method call onto the collection items. - * - * @param string $method - * @param array $parameters - * @return mixed - */ - public function __call($method, $parameters) - { - return $this->collection->{$this->method}(function ($value) use ($method, $parameters) { - return is_string($value) - ? $value::{$method}(...$parameters) - : $value->{$method}(...$parameters); - }); - } -} diff --git a/src/Illuminate/Support/HigherOrderWhenProxy.php b/src/Illuminate/Support/HigherOrderWhenProxy.php deleted file mode 100644 index 0a694c24f..000000000 --- a/src/Illuminate/Support/HigherOrderWhenProxy.php +++ /dev/null @@ -1,108 +0,0 @@ -target = $target; - } - - /** - * Set the condition on the proxy. - * - * @param bool $condition - * @return $this - */ - public function condition($condition) - { - [$this->condition, $this->hasCondition] = [$condition, true]; - - return $this; - } - - /** - * Indicate that the condition should be negated. - * - * @return $this - */ - public function negateConditionOnCapture() - { - $this->negateConditionOnCapture = true; - - return $this; - } - - /** - * Proxy accessing an attribute onto the target. - * - * @param string $key - * @return mixed - */ - public function __get($key) - { - if (! $this->hasCondition) { - $condition = $this->target->{$key}; - - return $this->condition($this->negateConditionOnCapture ? ! $condition : $condition); - } - - return $this->condition - ? $this->target->{$key} - : $this->target; - } - - /** - * Proxy a method call on the target. - * - * @param string $method - * @param array $parameters - * @return mixed - */ - public function __call($method, $parameters) - { - if (! $this->hasCondition) { - $condition = $this->target->{$method}(...$parameters); - - return $this->condition($this->negateConditionOnCapture ? ! $condition : $condition); - } - - return $this->condition - ? $this->target->{$method}(...$parameters) - : $this->target; - } -} diff --git a/src/Illuminate/Support/ItemNotFoundException.php b/src/Illuminate/Support/ItemNotFoundException.php deleted file mode 100644 index 05a51d954..000000000 --- a/src/Illuminate/Support/ItemNotFoundException.php +++ /dev/null @@ -1,9 +0,0 @@ - - */ -class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable -{ - /** - * @use \Illuminate\Support\Traits\EnumeratesValues - */ - use EnumeratesValues, Macroable; - - /** - * The source from which to generate items. - * - * @var (Closure(): \Generator)|static|array - */ - public $source; - - /** - * Create a new lazy collection instance. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable|(Closure(): \Generator)|self|array|null $source - * - * @throws \InvalidArgumentException - */ - public function __construct($source = null) - { - if ($source instanceof Closure || $source instanceof self) { - $this->source = $source; - } elseif (is_null($source)) { - $this->source = static::empty(); - } elseif ($source instanceof Generator) { - throw new InvalidArgumentException( - 'Generators should not be passed directly to LazyCollection. Instead, pass a generator function.' - ); - } else { - $this->source = $this->getArrayableItems($source); - } - } - - /** - * Create a new instance of the collection. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable|(Closure(): \Generator)|self|array|null $items - * @return static - */ - protected function newInstance($items = []) - { - return new static($items); - } - - /** - * Create a new collection instance if the value isn't one already. - * - * @template TMakeKey of array-key - * @template TMakeValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable|(Closure(): \Generator)|self|array|null $items - * @return static - */ - public static function make($items = [], ...$args) - { - return new static($items, ...$args); - } - - /** - * Create a collection with the given range. - * - * @param int $from - * @param int $to - * @param int $step - * @return ($step is 0 ? never : static) - * - * @throws \InvalidArgumentException - */ - public static function range($from, $to, $step = 1, ...$args) - { - if ($step == 0) { - throw new InvalidArgumentException('Step value cannot be zero.'); - } - - return new static(function () use ($from, $to, $step) { - if ($from <= $to) { - for (; $from <= $to; $from += abs($step)) { - yield $from; - } - } else { - for (; $from >= $to; $from -= abs($step)) { - yield $from; - } - } - }); - } - - /** - * Get all items in the enumerable. - * - * @return array - */ - public function all() - { - if (is_array($this->source)) { - return $this->source; - } - - return iterator_to_array($this->getIterator()); - } - - /** - * Eager load all items into a new lazy collection backed by an array. - * - * @return static - */ - public function eager() - { - return new static($this->all()); - } - - /** - * Cache values as they're enumerated. - * - * @return static - */ - public function remember() - { - $iterator = $this->getIterator(); - - $iteratorIndex = 0; - - $cache = []; - - return new static(function () use ($iterator, &$iteratorIndex, &$cache) { - for ($index = 0; true; $index++) { - if (array_key_exists($index, $cache)) { - yield $cache[$index][0] => $cache[$index][1]; - - continue; - } - - if ($iteratorIndex < $index) { - $iterator->next(); - - $iteratorIndex++; - } - - if (! $iterator->valid()) { - break; - } - - $cache[$index] = [$iterator->key(), $iterator->current()]; - - yield $cache[$index][0] => $cache[$index][1]; - } - }); - } - - /** - * Get the median of a given key. - * - * @param string|array|null $key - * @return float|int|null - */ - public function median($key = null) - { - return $this->collect()->median($key); - } - - /** - * Get the mode of a given key. - * - * @param string|array|null $key - * @return array|null - */ - public function mode($key = null) - { - return $this->collect()->mode($key); - } - - /** - * Collapse the collection of items into a single array. - * - * @return static - */ - public function collapse() - { - return new static(function () { - foreach ($this as $values) { - if (is_array($values) || $values instanceof Enumerable) { - foreach ($values as $value) { - yield $value; - } - } - } - }); - } - - /** - * Collapse the collection of items into a single array while preserving its keys. - * - * @return static - */ - public function collapseWithKeys() - { - return new static(function () { - foreach ($this as $values) { - if (is_array($values) || $values instanceof Enumerable) { - foreach ($values as $key => $value) { - yield $key => $value; - } - } - } - }); - } - - /** - * Determine if an item exists in the enumerable. - * - * @param (callable(TValue, TKey): bool)|TValue|string $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)) { - $placeholder = new stdClass; - - /** @var callable $key */ - return $this->first($key, $placeholder) !== $placeholder; - } - - if (func_num_args() === 1) { - $needle = $key; - - foreach ($this as $value) { - if ($value == $needle) { - return true; - } - } - - return false; - } - - return $this->contains($this->operatorForWhere(...func_get_args())); - } - - /** - * Determine if an item exists, using strict comparison. - * - * @param (callable(TValue): bool)|TValue|array-key $key - * @param TValue|null $value - * @return bool - */ - public function containsStrict($key, $value = null) - { - if (func_num_args() === 2) { - return $this->contains(fn ($item) => data_get($item, $key) === $value); - } - - if ($this->useAsCallable($key)) { - return ! is_null($this->first($key)); - } - - foreach ($this as $item) { - if ($item === $key) { - return true; - } - } - - return false; - } - - /** - * Determine if an item is not contained in the enumerable. - * - * @param mixed $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function doesntContain($key, $operator = null, $value = null) - { - return ! $this->contains(...func_get_args()); - } - - /** - * Determine if an item is not contained in the enumerable, using strict comparison. - * - * @param mixed $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function doesntContainStrict($key, $operator = null, $value = null) - { - return ! $this->containsStrict(...func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function crossJoin(...$arrays) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function countBy($countBy = null) - { - $countBy = is_null($countBy) - ? $this->identity() - : $this->valueRetriever($countBy); - - return new static(function () use ($countBy) { - $counts = []; - - foreach ($this as $key => $value) { - $group = enum_value($countBy($value, $key)); - - if (empty($counts[$group])) { - $counts[$group] = 0; - } - - $counts[$group]++; - } - - yield from $counts; - }); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function diff($items) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function diffUsing($items, callable $callback) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function diffAssoc($items) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function diffAssocUsing($items, callable $callback) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function diffKeys($items) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function diffKeysUsing($items, callable $callback) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function duplicates($callback = null, $strict = false) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function duplicatesStrict($callback = null) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function except($keys) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * Run a filter over each of the items. - * - * @param (callable(TValue, TKey): bool)|null $callback - * @return static - */ - public function filter(?callable $callback = null) - { - if (is_null($callback)) { - $callback = fn ($value) => (bool) $value; - } - - return new static(function () use ($callback) { - foreach ($this as $key => $value) { - if ($callback($value, $key)) { - yield $key => $value; - } - } - }); - } - - /** - * Get the first item from the enumerable passing the given truth test. - * - * @template TFirstDefault - * - * @param (callable(TValue): bool)|null $callback - * @param TFirstDefault|(\Closure(): TFirstDefault) $default - * @return TValue|TFirstDefault - */ - public function first(?callable $callback = null, $default = null) - { - $iterator = $this->getIterator(); - - if (is_null($callback)) { - if (! $iterator->valid()) { - return value($default); - } - - return $iterator->current(); - } - - foreach ($iterator as $key => $value) { - if ($callback($value, $key)) { - return $value; - } - } - - return value($default); - } - - /** - * Get a flattened list of the items in the collection. - * - * @param int $depth - * @return static - */ - public function flatten($depth = INF) - { - $instance = new static(function () use ($depth) { - foreach ($this as $item) { - if (! is_array($item) && ! $item instanceof Enumerable) { - yield $item; - } elseif ($depth === 1) { - yield from $item; - } else { - yield from (new static($item))->flatten($depth - 1); - } - } - }); - - return $instance->values(); - } - - /** - * Flip the items in the collection. - * - * @return static - */ - public function flip() - { - return new static(function () { - foreach ($this as $key => $value) { - if (is_string($value) || is_int($value)) { - yield $value => $key; - } - } - }); - } - - /** - * Get an item by key. - * - * @template TGetDefault - * - * @param TKey|null $key - * @param TGetDefault|(\Closure(): TGetDefault) $default - * @return TValue|TGetDefault - */ - public function get($key, $default = null) - { - if (is_null($key)) { - return; - } - - foreach ($this as $outerKey => $outerValue) { - if ($outerKey == $key) { - return $outerValue; - } - } - - return value($default); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function groupBy($groupBy, $preserveKeys = false) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function keyBy($keyBy) - { - return new static(function () use ($keyBy) { - $keyBy = $this->valueRetriever($keyBy); - - foreach ($this as $key => $item) { - $resolvedKey = $keyBy($item, $key); - - if ($resolvedKey instanceof \UnitEnum) { - $resolvedKey = enum_value($resolvedKey); - } - - if (is_object($resolvedKey) || is_null($resolvedKey)) { - $resolvedKey = (string) $resolvedKey; - } - - yield $resolvedKey => $item; - } - }); - } - - /** - * Determine if an item exists in the collection by key. - * - * @param mixed $key - * @return bool - */ - public function has($key) - { - $keys = array_flip(is_array($key) ? $key : func_get_args()); - - foreach ($this as $key => $value) { - unset($keys[$key]); - - if (empty($keys)) { - return true; - } - } - - return false; - } - - /** - * Determine if any of the keys exist in the collection. - * - * @param mixed $key - * @return bool - */ - public function hasAny($key) - { - $keys = array_flip(is_array($key) ? $key : func_get_args()); - - foreach ($this as $key => $value) { - if (array_key_exists($key, $keys)) { - return true; - } - } - - return false; - } - - /** - * Concatenate values of a given key as a string. - * - * @param (callable(TValue, TKey): mixed)|string $value - * @param string|null $glue - * @return string - */ - public function implode($value, $glue = null) - { - return $this->collect()->implode(...func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function intersect($items) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function intersectUsing($items, callable $callback) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function intersectAssoc($items) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function intersectAssocUsing($items, callable $callback) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function intersectByKeys($items) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * Determine if the items are empty or not. - * - * @return bool - */ - public function isEmpty() - { - return ! $this->getIterator()->valid(); - } - - /** - * Determine if the collection contains a single item. - * - * @param (callable(TValue, TKey): bool)|null $callback - * @return bool - * - * @deprecated 12.49.0 Use the `hasSole()` method instead. - */ - public function containsOneItem(?callable $callback = null): bool - { - return $this->hasSole($callback); - } - - /** - * Determine if the collection contains multiple items. - * - * @return bool - * - * @deprecated 12.50.0 Use the `hasMany()` method instead. - */ - public function containsManyItems(): bool - { - return $this->hasMany(); - } - - /** - * Join all items from the collection using a string. The final items can use a separate glue string. - * - * @param string $glue - * @param string $finalGlue - * @return string - */ - public function join($glue, $finalGlue = '') - { - return $this->collect()->join(...func_get_args()); - } - - /** - * Get the keys of the collection items. - * - * @return static - */ - public function keys() - { - return new static(function () { - foreach ($this as $key => $value) { - yield $key; - } - }); - } - - /** - * Get the last item from the collection. - * - * @template TLastDefault - * - * @param (callable(TValue, TKey): bool)|null $callback - * @param TLastDefault|(\Closure(): TLastDefault) $default - * @return TValue|TLastDefault - */ - public function last(?callable $callback = null, $default = null) - { - $needle = $placeholder = new stdClass; - - foreach ($this as $key => $value) { - if (is_null($callback) || $callback($value, $key)) { - $needle = $value; - } - } - - return $needle === $placeholder ? value($default) : $needle; - } - - /** - * Get the values of a given key. - * - * @param string|array $value - * @param string|null $key - * @return static - */ - public function pluck($value, $key = null) - { - return new static(function () use ($value, $key) { - [$value, $key] = $this->explodePluckParameters($value, $key); - - foreach ($this as $item) { - $itemValue = $value instanceof Closure - ? $value($item) - : data_get($item, $value); - - if (is_null($key)) { - yield $itemValue; - } else { - $itemKey = $key instanceof Closure - ? $key($item) - : data_get($item, $key); - - if (is_object($itemKey) && method_exists($itemKey, '__toString')) { - $itemKey = (string) $itemKey; - } - - yield $itemKey => $itemValue; - } - } - }); - } - - /** - * Run a map over each of the items. - * - * @template TMapValue - * - * @param callable(TValue, TKey): TMapValue $callback - * @return static - */ - public function map(callable $callback) - { - return new static(function () use ($callback) { - foreach ($this as $key => $value) { - yield $key => $callback($value, $key); - } - }); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function mapToDictionary(callable $callback) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * Run an associative map over each of the items. - * - * The callback should return an associative array with a single key/value pair. - * - * @template TMapWithKeysKey of array-key - * @template TMapWithKeysValue - * - * @param callable(TValue, TKey): array $callback - * @return static - */ - public function mapWithKeys(callable $callback) - { - return new static(function () use ($callback) { - foreach ($this as $key => $value) { - yield from $callback($value, $key); - } - }); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function merge($items) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function mergeRecursive($items) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * Multiply the items in the collection by the multiplier. - * - * @param int $multiplier - * @return static - */ - public function multiply(int $multiplier) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * Create a collection by using this collection for keys and another for its values. - * - * @template TCombineValue - * - * @param \IteratorAggregate|array|(callable(): \Generator) $values - * @return static - */ - public function combine($values) - { - return new static(function () use ($values) { - $values = $this->makeIterator($values); - - $errorMessage = 'Both parameters should have an equal number of elements'; - - foreach ($this as $key) { - if (! $values->valid()) { - trigger_error($errorMessage, E_USER_WARNING); - - break; - } - - yield $key => $values->current(); - - $values->next(); - } - - if ($values->valid()) { - trigger_error($errorMessage, E_USER_WARNING); - } - }); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function union($items) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * Create a new collection consisting of every n-th element. - * - * @param int $step - * @param int $offset - * @return ($step is positive-int ? static : never) - * - * @throws \InvalidArgumentException - */ - public function nth($step, $offset = 0) - { - if ($step < 1) { - throw new InvalidArgumentException('Step value must be at least 1.'); - } - - return new static(function () use ($step, $offset) { - $position = 0; - - foreach ($this->slice($offset) as $item) { - if ($position % $step === 0) { - yield $item; - } - - $position++; - } - }); - } - - /** - * Get the items with the specified keys. - * - * @param \Illuminate\Support\Enumerable|array|string $keys - * @return static - */ - public function only($keys) - { - if ($keys instanceof Enumerable) { - $keys = $keys->all(); - } elseif (! is_null($keys)) { - $keys = is_array($keys) ? $keys : func_get_args(); - } - - return new static(function () use ($keys) { - if (is_null($keys)) { - yield from $this; - } else { - $keys = array_flip($keys); - - foreach ($this as $key => $value) { - if (array_key_exists($key, $keys)) { - yield $key => $value; - - unset($keys[$key]); - - if (empty($keys)) { - break; - } - } - } - } - }); - } - - /** - * Select specific values from the items within the collection. - * - * @param \Illuminate\Support\Enumerable|array|string $keys - * @return static - */ - public function select($keys) - { - if ($keys instanceof Enumerable) { - $keys = $keys->all(); - } elseif (! is_null($keys)) { - $keys = is_array($keys) ? $keys : func_get_args(); - } - - return new static(function () use ($keys) { - if (is_null($keys)) { - yield from $this; - } else { - foreach ($this as $item) { - $result = []; - - foreach ($keys as $key) { - if (Arr::accessible($item) && Arr::exists($item, $key)) { - $result[$key] = $item[$key]; - } elseif (is_object($item) && isset($item->{$key})) { - $result[$key] = $item->{$key}; - } - } - - yield $result; - } - } - }); - } - - /** - * Push all of the given items onto the collection. - * - * @template TConcatKey of array-key - * @template TConcatValue - * - * @param iterable $source - * @return static - */ - public function concat($source) - { - return (new static(function () use ($source) { - yield from $this; - yield from $source; - }))->values(); - } - - /** - * Get one or a specified number of items randomly from the collection. - * - * @param int|null $number - * @param bool $preserveKeys - * @return ($number is null ? TValue : static) - * - * @throws \InvalidArgumentException - */ - public function random($number = null, $preserveKeys = false) - { - $result = $this->collect()->random(...func_get_args()); - - return is_null($number) ? $result : new static($result); - } - - /** - * Replace the collection items with the given items. - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable $items - * @return static - */ - public function replace($items) - { - return new static(function () use ($items) { - $items = $this->getArrayableItems($items); - - foreach ($this as $key => $value) { - if (array_key_exists($key, $items)) { - yield $key => $items[$key]; - - unset($items[$key]); - } else { - yield $key => $value; - } - } - - foreach ($items as $key => $value) { - yield $key => $value; - } - }); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function replaceRecursive($items) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function reverse() - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * Search the collection for a given value and return the corresponding key if successful. - * - * @param TValue|(callable(TValue,TKey): bool) $value - * @param bool $strict - * @return TKey|false - */ - public function search($value, $strict = false) - { - /** @var (callable(TValue,TKey): bool) $predicate */ - $predicate = $this->useAsCallable($value) - ? $value - : function ($item) use ($value, $strict) { - return $strict ? $item === $value : $item == $value; - }; - - foreach ($this as $key => $item) { - if ($predicate($item, $key)) { - return $key; - } - } - - return false; - } - - /** - * Get the item before the given item. - * - * @param TValue|(callable(TValue,TKey): bool) $value - * @param bool $strict - * @return TValue|null - */ - public function before($value, $strict = false) - { - $previous = null; - - /** @var (callable(TValue,TKey): bool) $predicate */ - $predicate = $this->useAsCallable($value) - ? $value - : function ($item) use ($value, $strict) { - return $strict ? $item === $value : $item == $value; - }; - - foreach ($this as $key => $item) { - if ($predicate($item, $key)) { - return $previous; - } - - $previous = $item; - } - - return null; - } - - /** - * Get the item after the given item. - * - * @param TValue|(callable(TValue,TKey): bool) $value - * @param bool $strict - * @return TValue|null - */ - public function after($value, $strict = false) - { - $found = false; - - /** @var (callable(TValue,TKey): bool) $predicate */ - $predicate = $this->useAsCallable($value) - ? $value - : function ($item) use ($value, $strict) { - return $strict ? $item === $value : $item == $value; - }; - - foreach ($this as $key => $item) { - if ($found) { - return $item; - } - - if ($predicate($item, $key)) { - $found = true; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function shuffle() - { - return $this->passthru(__FUNCTION__, []); - } - - /** - * Create chunks representing a "sliding window" view of the items in the collection. - * - * @param positive-int $size - * @param positive-int $step - * @return static - * - * @throws \InvalidArgumentException - */ - public function sliding($size = 2, $step = 1) - { - if ($size < 1) { - throw new InvalidArgumentException('Size value must be at least 1.'); - } elseif ($step < 1) { - throw new InvalidArgumentException('Step value must be at least 1.'); - } - - return new static(function () use ($size, $step) { - $iterator = $this->getIterator(); - - $chunk = []; - - while ($iterator->valid()) { - $chunk[$iterator->key()] = $iterator->current(); - - if (count($chunk) == $size) { - yield (new static($chunk))->tap(function () use (&$chunk, $step) { - $chunk = array_slice($chunk, $step, null, true); - }); - - // If the $step between chunks is bigger than each chunk's $size - // we will skip the extra items (which should never be in any - // chunk) before we continue to the next chunk in the loop. - if ($step > $size) { - $skip = $step - $size; - - for ($i = 0; $i < $skip && $iterator->valid(); $i++) { - $iterator->next(); - } - } - } - - $iterator->next(); - } - }); - } - - /** - * Skip the first {$count} items. - * - * @param int $count - * @return static - */ - public function skip($count) - { - return new static(function () use ($count) { - $iterator = $this->getIterator(); - - while ($iterator->valid() && $count--) { - $iterator->next(); - } - - while ($iterator->valid()) { - yield $iterator->key() => $iterator->current(); - - $iterator->next(); - } - }); - } - - /** - * Skip items in the collection until the given condition is met. - * - * @param TValue|callable(TValue,TKey): bool $value - * @return static - */ - public function skipUntil($value) - { - $callback = $this->useAsCallable($value) ? $value : $this->equality($value); - - return $this->skipWhile($this->negate($callback)); - } - - /** - * Skip items in the collection while the given condition is met. - * - * @param TValue|callable(TValue,TKey): bool $value - * @return static - */ - public function skipWhile($value) - { - $callback = $this->useAsCallable($value) ? $value : $this->equality($value); - - return new static(function () use ($callback) { - $iterator = $this->getIterator(); - - while ($iterator->valid() && $callback($iterator->current(), $iterator->key())) { - $iterator->next(); - } - - while ($iterator->valid()) { - yield $iterator->key() => $iterator->current(); - - $iterator->next(); - } - }); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function slice($offset, $length = null) - { - if ($offset < 0 || $length < 0) { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - $instance = $this->skip($offset); - - return is_null($length) ? $instance : $instance->take($length); - } - - /** - * {@inheritDoc} - * - * @throws \InvalidArgumentException - */ - #[\Override] - public function split($numberOfGroups) - { - if ($numberOfGroups < 1) { - throw new InvalidArgumentException('Number of groups must be at least 1.'); - } - - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception. - * - * @param (callable(TValue, TKey): bool)|string|null $key - * @param mixed $operator - * @param mixed $value - * @return TValue - * - * @throws \Illuminate\Support\ItemNotFoundException - * @throws \Illuminate\Support\MultipleItemsFoundException - */ - public function sole($key = null, $operator = null, $value = null) - { - $filter = func_num_args() > 1 - ? $this->operatorForWhere(...func_get_args()) - : $key; - - return $this - ->unless($filter == null) - ->filter($filter) - ->take(2) - ->collect() - ->sole(); - } - - /** - * Determine if the collection contains a single item or a single item matching the given criteria. - * - * @param (callable(TValue, TKey): bool)|string|null $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function hasSole($key = null, $operator = null, $value = null): bool - { - $filter = func_num_args() > 1 - ? $this->operatorForWhere(...func_get_args()) - : $key; - - return $this - ->unless($filter == null) - ->filter($filter) - ->take(2) - ->count() === 1; - } - - /** - * Get the first item in the collection but throw an exception if no matching items exist. - * - * @param (callable(TValue, TKey): bool)|string|null $key - * @param mixed $operator - * @param mixed $value - * @return TValue - * - * @throws \Illuminate\Support\ItemNotFoundException - */ - public function firstOrFail($key = null, $operator = null, $value = null) - { - $filter = func_num_args() > 1 - ? $this->operatorForWhere(...func_get_args()) - : $key; - - return $this - ->unless($filter == null) - ->filter($filter) - ->take(1) - ->collect() - ->firstOrFail(); - } - - /** - * Chunk the collection into chunks of the given size. - * - * @param int $size - * @param bool $preserveKeys - * @return ($preserveKeys is true ? static : static>) - */ - public function chunk($size, $preserveKeys = true) - { - if ($size <= 0) { - return static::empty(); - } - - $add = match ($preserveKeys) { - true => fn (array &$chunk, Traversable $iterator) => $chunk[$iterator->key()] = $iterator->current(), - false => fn (array &$chunk, Traversable $iterator) => $chunk[] = $iterator->current(), - }; - - return new static(function () use ($size, $add) { - $iterator = $this->getIterator(); - - while ($iterator->valid()) { - $chunk = []; - - while (true) { - $add($chunk, $iterator); - - if (count($chunk) < $size) { - $iterator->next(); - - if (! $iterator->valid()) { - break; - } - } else { - break; - } - } - - yield new static($chunk); - - $iterator->next(); - } - }); - } - - /** - * Split a collection into a certain number of groups, and fill the first groups completely. - * - * @param int $numberOfGroups - * @return ($numberOfGroups is positive-int ? static : never) - * - * @throws \InvalidArgumentException - */ - public function splitIn($numberOfGroups) - { - if ($numberOfGroups < 1) { - throw new InvalidArgumentException('Number of groups must be at least 1.'); - } - - return $this->chunk((int) ceil($this->count() / $numberOfGroups)); - } - - /** - * Chunk the collection into chunks with a callback. - * - * @param callable(TValue, TKey, Collection): bool $callback - * @return static> - */ - public function chunkWhile(callable $callback) - { - return new static(function () use ($callback) { - $iterator = $this->getIterator(); - - $chunk = new Collection; - - if ($iterator->valid()) { - $chunk[$iterator->key()] = $iterator->current(); - - $iterator->next(); - } - - while ($iterator->valid()) { - if (! $callback($iterator->current(), $iterator->key(), $chunk)) { - yield new static($chunk); - - $chunk = new Collection; - } - - $chunk[$iterator->key()] = $iterator->current(); - - $iterator->next(); - } - - if ($chunk->isNotEmpty()) { - yield new static($chunk); - } - }); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function sort($callback = null) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function sortDesc($options = SORT_REGULAR) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function sortBy($callback, $options = SORT_REGULAR, $descending = false) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function sortByDesc($callback, $options = SORT_REGULAR) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function sortKeys($options = SORT_REGULAR, $descending = false) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function sortKeysDesc($options = SORT_REGULAR) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function sortKeysUsing(callable $callback) - { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - /** - * Take the first or last {$limit} items. - * - * @param int $limit - * @return static - */ - public function take($limit) - { - if ($limit < 0) { - return new static(function () use ($limit) { - $limit = abs($limit); - $ringBuffer = []; - $position = 0; - - foreach ($this as $key => $value) { - $ringBuffer[$position] = [$key, $value]; - $position = ($position + 1) % $limit; - } - - for ($i = 0, $end = min($limit, count($ringBuffer)); $i < $end; $i++) { - $pointer = ($position + $i) % $limit; - yield $ringBuffer[$pointer][0] => $ringBuffer[$pointer][1]; - } - }); - } - - return new static(function () use ($limit) { - $iterator = $this->getIterator(); - - while ($limit--) { - if (! $iterator->valid()) { - break; - } - - yield $iterator->key() => $iterator->current(); - - if ($limit) { - $iterator->next(); - } - } - }); - } - - /** - * Take items in the collection until the given condition is met. - * - * @param TValue|callable(TValue,TKey): bool $value - * @return static - */ - public function takeUntil($value) - { - /** @var callable(TValue, TKey): bool $callback */ - $callback = $this->useAsCallable($value) ? $value : $this->equality($value); - - return new static(function () use ($callback) { - foreach ($this as $key => $item) { - if ($callback($item, $key)) { - break; - } - - yield $key => $item; - } - }); - } - - /** - * Take items in the collection until a given point in time, with an optional callback on timeout. - * - * @param \DateTimeInterface $timeout - * @param callable(TValue|null, TKey|null): mixed|null $callback - * @return static - */ - public function takeUntilTimeout(DateTimeInterface $timeout, ?callable $callback = null) - { - $timeout = $timeout->getTimestamp(); - - return new static(function () use ($timeout, $callback) { - if ($this->now() >= $timeout) { - if ($callback) { - $callback(null, null); - } - - return; - } - - foreach ($this as $key => $value) { - yield $key => $value; - - if ($this->now() >= $timeout) { - if ($callback) { - $callback($value, $key); - } - - break; - } - } - }); - } - - /** - * Take items in the collection while the given condition is met. - * - * @param TValue|callable(TValue,TKey): bool $value - * @return static - */ - public function takeWhile($value) - { - /** @var callable(TValue, TKey): bool $callback */ - $callback = $this->useAsCallable($value) ? $value : $this->equality($value); - - return $this->takeUntil(fn ($item, $key) => ! $callback($item, $key)); - } - - /** - * Pass each item in the collection to the given callback, lazily. - * - * @param callable(TValue, TKey): mixed $callback - * @return static - */ - public function tapEach(callable $callback) - { - return new static(function () use ($callback) { - foreach ($this as $key => $value) { - $callback($value, $key); - - yield $key => $value; - } - }); - } - - /** - * Throttle the values, releasing them at most once per the given seconds. - * - * @return static - */ - public function throttle(float $seconds) - { - return new static(function () use ($seconds) { - $microseconds = $seconds * 1_000_000; - - foreach ($this as $key => $value) { - $fetchedAt = $this->preciseNow(); - - yield $key => $value; - - $sleep = $microseconds - ($this->preciseNow() - $fetchedAt); - - $this->usleep((int) $sleep); - } - }); - } - - /** - * Flatten a multi-dimensional associative array with dots. - * - * @param int $depth - * @return static - */ - public function dot($depth = INF) - { - return $this->passthru(__FUNCTION__, [$depth]); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function undot() - { - return $this->passthru(__FUNCTION__, []); - } - - /** - * Return only unique items from the collection array. - * - * @param (callable(TValue, TKey): mixed)|string|null $key - * @param bool $strict - * @return static - */ - public function unique($key = null, $strict = false) - { - $callback = $this->valueRetriever($key); - - return new static(function () use ($callback, $strict) { - $exists = []; - - foreach ($this as $key => $item) { - if (! in_array($id = $callback($item, $key), $exists, $strict)) { - yield $key => $item; - - $exists[] = $id; - } - } - }); - } - - /** - * Reset the keys on the underlying array. - * - * @return static - */ - public function values() - { - return new static(function () { - foreach ($this as $item) { - yield $item; - } - }); - } - - /** - * Run the given callback every time the interval has passed. - * - * @return static - */ - public function withHeartbeat(DateInterval|int $interval, callable $callback) - { - $seconds = is_int($interval) ? $interval : $this->intervalSeconds($interval); - - return new static(function () use ($seconds, $callback) { - $start = $this->now(); - - foreach ($this as $key => $value) { - $now = $this->now(); - - if (($now - $start) >= $seconds) { - $callback(); - - $start = $now; - } - - yield $key => $value; - } - }); - } - - /** - * Get the total seconds from the given interval. - */ - protected function intervalSeconds(DateInterval $interval): int - { - $start = new DateTimeImmutable(); - - return $start->add($interval)->getTimestamp() - $start->getTimestamp(); - } - - /** - * Zip the collection together with one or more arrays. - * - * e.g. new LazyCollection([1, 2, 3])->zip([4, 5, 6]); - * => [[1, 4], [2, 5], [3, 6]] - * - * @template TZipValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable ...$items - * @return static> - */ - public function zip($items) - { - $iterables = func_get_args(); - - return new static(function () use ($iterables) { - $iterators = (new Collection($iterables)) - ->map(fn ($iterable) => $this->makeIterator($iterable)) - ->prepend($this->getIterator()); - - while ($iterators->contains->valid()) { - yield new static($iterators->map->current()); - - $iterators->each->next(); - } - }); - } - - /** - * {@inheritDoc} - */ - #[\Override] - public function pad($size, $value) - { - if ($size < 0) { - return $this->passthru(__FUNCTION__, func_get_args()); - } - - return new static(function () use ($size, $value) { - $yielded = 0; - - foreach ($this as $index => $item) { - yield $index => $item; - - $yielded++; - } - - while ($yielded++ < $size) { - yield $value; - } - }); - } - - /** - * Get the values iterator. - * - * @return \Traversable - */ - public function getIterator(): Traversable - { - return $this->makeIterator($this->source); - } - - /** - * Count the number of items in the collection. - * - * @return int - */ - public function count(): int - { - if (is_array($this->source)) { - return count($this->source); - } - - return iterator_count($this->getIterator()); - } - - /** - * Make an iterator from the given source. - * - * @template TIteratorKey of array-key - * @template TIteratorValue - * - * @param \IteratorAggregate|array|(callable(): \Generator) $source - * @return \Traversable - */ - protected function makeIterator($source) - { - if ($source instanceof IteratorAggregate) { - return $source->getIterator(); - } - - if (is_array($source)) { - return new ArrayIterator($source); - } - - if (is_callable($source)) { - $maybeTraversable = $source(); - - return $maybeTraversable instanceof Traversable - ? $maybeTraversable - : new ArrayIterator(Arr::wrap($maybeTraversable)); - } - - return new ArrayIterator((array) $source); - } - - /** - * Explode the "value" and "key" arguments passed to "pluck". - * - * @param string|string[] $value - * @param string|string[]|null $key - * @return array{string[],string[]|null} - */ - protected function explodePluckParameters($value, $key) - { - $value = is_string($value) ? explode('.', $value) : $value; - - $key = is_null($key) || is_array($key) || $key instanceof Closure ? $key : explode('.', $key); - - return [$value, $key]; - } - - /** - * Pass this lazy collection through a method on the collection class. - * - * @param string $method - * @param array $params - * @return static - */ - protected function passthru($method, array $params) - { - return new static(function () use ($method, $params) { - yield from $this->collect()->$method(...$params); - }); - } - - /** - * Get the current time. - * - * @return int - */ - protected function now() - { - return class_exists(Carbon::class) - ? Carbon::now()->getTimestamp() - : time(); - } - - /** - * Get the precise current time. - * - * @return float - */ - protected function preciseNow() - { - return class_exists(Carbon::class) - ? Carbon::now()->getPreciseTimestamp() - : microtime(true) * 1_000_000; - } - - /** - * Sleep for the given amount of microseconds. - * - * @return void - */ - protected function usleep(int $microseconds) - { - if ($microseconds <= 0) { - return; - } - - class_exists(Sleep::class) - ? Sleep::usleep($microseconds) - : usleep($microseconds); - } -} diff --git a/src/Illuminate/Support/MultipleItemsFoundException.php b/src/Illuminate/Support/MultipleItemsFoundException.php deleted file mode 100644 index 9c5c7c560..000000000 --- a/src/Illuminate/Support/MultipleItemsFoundException.php +++ /dev/null @@ -1,39 +0,0 @@ -count = $count; - - parent::__construct("$count items were found.", $code, $previous); - } - - /** - * Get the number of items found. - * - * @return int - */ - public function getCount() - { - return $this->count; - } -} diff --git a/src/Illuminate/Support/Reflector.php b/src/Illuminate/Support/Reflector.php deleted file mode 100644 index e96f41ed5..000000000 --- a/src/Illuminate/Support/Reflector.php +++ /dev/null @@ -1,40 +0,0 @@ -getType(); - - if (! $type instanceof ReflectionNamedType || $type->isBuiltin()) { - return null; - } - - $name = $type->getName(); - - if (! is_null($class = $parameter->getDeclaringClass())) { - if ($name === 'self') { - return $class->getName(); - } - - if ($name === 'parent' && $parent = $class->getParentClass()) { - return $parent->getName(); - } - } - - return $name; - } -} \ No newline at end of file diff --git a/src/Illuminate/Support/Traits/Conditionable.php b/src/Illuminate/Support/Traits/Conditionable.php deleted file mode 100644 index 5e3194bbc..000000000 --- a/src/Illuminate/Support/Traits/Conditionable.php +++ /dev/null @@ -1,73 +0,0 @@ -condition($value); - } - - if ($value) { - return $callback($this, $value) ?? $this; - } elseif ($default) { - return $default($this, $value) ?? $this; - } - - return $this; - } - - /** - * Apply the callback if the given "value" is (or resolves to) falsy. - * - * @template TUnlessParameter - * @template TUnlessReturnType - * - * @param (\Closure($this): TUnlessParameter)|TUnlessParameter|null $value - * @param (callable($this, TUnlessParameter): TUnlessReturnType)|null $callback - * @param (callable($this, TUnlessParameter): TUnlessReturnType)|null $default - * @return $this|TUnlessReturnType - */ - public function unless($value = null, ?callable $callback = null, ?callable $default = null) - { - $value = $value instanceof Closure ? $value($this) : $value; - - if (func_num_args() === 0) { - return (new HigherOrderWhenProxy($this))->negateConditionOnCapture(); - } - - if (func_num_args() === 1) { - return (new HigherOrderWhenProxy($this))->condition(! $value); - } - - if (! $value) { - return $callback($this, $value) ?? $this; - } elseif ($default) { - return $default($this, $value) ?? $this; - } - - return $this; - } -} diff --git a/src/Illuminate/Support/Traits/EnumeratesValues.php b/src/Illuminate/Support/Traits/EnumeratesValues.php deleted file mode 100644 index fbd7c90d7..000000000 --- a/src/Illuminate/Support/Traits/EnumeratesValues.php +++ /dev/null @@ -1,1244 +0,0 @@ - $average - * @property-read HigherOrderCollectionProxy $avg - * @property-read HigherOrderCollectionProxy $contains - * @property-read HigherOrderCollectionProxy $doesntContain - * @property-read HigherOrderCollectionProxy $each - * @property-read HigherOrderCollectionProxy $every - * @property-read HigherOrderCollectionProxy $filter - * @property-read HigherOrderCollectionProxy $first - * @property-read HigherOrderCollectionProxy $flatMap - * @property-read HigherOrderCollectionProxy $groupBy - * @property-read HigherOrderCollectionProxy $hasMany - * @property-read HigherOrderCollectionProxy $hasSole - * @property-read HigherOrderCollectionProxy $keyBy - * @property-read HigherOrderCollectionProxy $last - * @property-read HigherOrderCollectionProxy $map - * @property-read HigherOrderCollectionProxy $max - * @property-read HigherOrderCollectionProxy $min - * @property-read HigherOrderCollectionProxy $partition - * @property-read HigherOrderCollectionProxy $percentage - * @property-read HigherOrderCollectionProxy $reject - * @property-read HigherOrderCollectionProxy $skipUntil - * @property-read HigherOrderCollectionProxy $skipWhile - * @property-read HigherOrderCollectionProxy $some - * @property-read HigherOrderCollectionProxy $sortBy - * @property-read HigherOrderCollectionProxy $sortByDesc - * @property-read HigherOrderCollectionProxy $sum - * @property-read HigherOrderCollectionProxy $takeUntil - * @property-read HigherOrderCollectionProxy $takeWhile - * @property-read HigherOrderCollectionProxy $unique - * @property-read HigherOrderCollectionProxy $unless - * @property-read HigherOrderCollectionProxy $until - * @property-read HigherOrderCollectionProxy $when - */ -trait EnumeratesValues -{ - use Conditionable; - - /** - * Indicates that the object's string representation should be escaped when __toString is invoked. - * - * @var bool - */ - protected $escapeWhenCastingToString = false; - - /** - * The methods that can be proxied. - * - * @var array - */ - protected static $proxies = [ - 'average', - 'avg', - 'contains', - 'doesntContain', - 'each', - 'every', - 'filter', - 'first', - 'flatMap', - 'groupBy', - 'hasMany', - 'hasSole', - 'keyBy', - 'last', - 'map', - 'max', - 'min', - 'partition', - 'percentage', - 'reject', - 'skipUntil', - 'skipWhile', - 'some', - 'sortBy', - 'sortByDesc', - 'sum', - 'takeUntil', - 'takeWhile', - 'unique', - 'unless', - 'until', - 'when', - ]; - - /** - * Create a new collection instance if the value isn't one already. - * - * @template TMakeKey of array-key - * @template TMakeValue - * - * @param \Illuminate\Contracts\Support\Arrayable|iterable|null $items - * @return static - */ - public static function make($items = [], ...$args) - { - return new static($items, ...$args); - } - - /** - * Wrap the given value in a collection if applicable. - * - * @template TWrapValue - * - * @param iterable|TWrapValue $value - * @return static - */ - public static function wrap($value, ...$args) - { - return $value instanceof Enumerable - ? new static($value, ...$args) - : new static(Arr::wrap($value), ...$args); - } - - /** - * Get the underlying items from the given collection if applicable. - * - * @template TUnwrapKey of array-key - * @template TUnwrapValue - * - * @param array|static $value - * @return array - */ - public static function unwrap($value) - { - return $value instanceof Enumerable ? $value->all() : $value; - } - - /** - * Create a new instance with no items. - * - * @return static - */ - public static function empty(...$args) - { - return new static([], ...$args); - } - - /** - * Create a new collection by invoking the callback a given amount of times. - * - * @template TTimesValue - * - * @param int $number - * @param (callable(int): TTimesValue)|null $callback - * @return static - */ - public static function times($number, ?callable $callback = null, ...$args) - { - if ($number < 1) { - return new static([], ...$args); - } - - return static::range(1, $number, 1, ...$args) - ->unless($callback == null) - ->map($callback); - } - - /** - * Create a new collection by decoding a JSON string. - * - * @param string $json - * @param int $depth - * @param int $flags - * @return static - */ - public static function fromJson($json, $depth = 512, $flags = 0, ...$args) - { - return new static(json_decode($json, true, $depth, $flags), ...$args); - } - - /** - * Get the average value of a given key. - * - * @param (callable(TValue): float|int)|string|null $callback - * @return float|int|null - */ - public function avg($callback = null) - { - $callback = $this->valueRetriever($callback); - - $reduced = $this->reduce(static function (&$reduce, $value) use ($callback) { - if (! is_null($resolved = $callback($value))) { - $reduce[0] += $resolved; - $reduce[1]++; - } - - return $reduce; - }, [0, 0]); - - return $reduced[1] ? $reduced[0] / $reduced[1] : null; - } - - /** - * Alias for the "avg" method. - * - * @param (callable(TValue): float|int)|string|null $callback - * @return float|int|null - */ - public function average($callback = null) - { - return $this->avg($callback); - } - - /** - * Alias for the "contains" method. - * - * @param (callable(TValue, TKey): bool)|TValue|string $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function some($key, $operator = null, $value = null) - { - return $this->contains(...func_get_args()); - } - - /** - * Dump the given arguments and terminate execution. - * - * @param mixed ...$args - * @return never - */ - public function dd(...$args) - { - dd($this->all(), ...$args); - } - - /** - * Dump the items. - * - * @param mixed ...$args - * @return $this - */ - public function dump(...$args) - { - dump($this->all(), ...$args); - - return $this; - } - - /** - * Execute a callback over each item. - * - * @param callable(TValue, TKey): mixed $callback - * @return $this - */ - public function each(callable $callback) - { - foreach ($this as $key => $item) { - if ($callback($item, $key) === false) { - break; - } - } - - return $this; - } - - /** - * Execute a callback over each nested chunk of items. - * - * @param callable(...mixed): mixed $callback - * @return static - */ - public function eachSpread(callable $callback) - { - return $this->each(function ($chunk, $key) use ($callback) { - $chunk[] = $key; - - return $callback(...$chunk); - }); - } - - /** - * Determine if all items pass the given truth test. - * - * @param (callable(TValue, TKey): bool)|TValue|string $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function every($key, $operator = null, $value = null) - { - if (func_num_args() === 1) { - $callback = $this->valueRetriever($key); - - foreach ($this as $k => $v) { - if (! $callback($v, $k)) { - return false; - } - } - - return true; - } - - return $this->every($this->operatorForWhere(...func_get_args())); - } - - /** - * Get the first item by the given key value pair. - * - * @param callable|string $key - * @param mixed $operator - * @param mixed $value - * @return TValue|null - */ - public function firstWhere($key, $operator = null, $value = null) - { - return $this->first($this->operatorForWhere(...func_get_args())); - } - - /** - * Determine if the collection contains multiple items, optionally matching the given criteria. - * - * @param (callable(TValue, TKey): bool)|string|null $key - * @param mixed $operator - * @param mixed $value - * @return bool - */ - public function hasMany($key = null, $operator = null, $value = null): bool - { - $filter = func_num_args() > 1 - ? $this->operatorForWhere(...func_get_args()) - : $key; - - return $this - ->unless($filter == null) - ->filter($filter) - ->take(2) - ->count() === 2; - } - - /** - * Get a single key's value from the first matching item in the collection. - * - * @template TValueDefault - * - * @param string $key - * @param TValueDefault|(\Closure(): TValueDefault) $default - * @return TValue|TValueDefault - */ - public function value($key, $default = null) - { - $value = $this->first(function ($target) use ($key) { - return data_has($target, $key); - }); - - return data_get($value, $key, $default); - } - - /** - * Ensure that every item in the collection is of the expected type. - * - * @template TEnsureOfType - * - * @param class-string|array>|'string'|'int'|'float'|'bool'|'array'|'null' $type - * @return static - * - * @throws \UnexpectedValueException - */ - public function ensure($type) - { - $allowedTypes = is_array($type) ? $type : [$type]; - - return $this->each(function ($item, $index) use ($allowedTypes) { - $itemType = get_debug_type($item); - - foreach ($allowedTypes as $allowedType) { - if ($itemType === $allowedType || $item instanceof $allowedType) { - return true; - } - } - - throw new UnexpectedValueException( - sprintf("Collection should only include [%s] items, but '%s' found at position %d.", implode(', ', $allowedTypes), $itemType, $index) - ); - }); - } - - /** - * Determine if the collection is not empty. - * - * @phpstan-assert-if-true TValue $this->first() - * @phpstan-assert-if-true TValue $this->last() - * - * @phpstan-assert-if-false null $this->first() - * @phpstan-assert-if-false null $this->last() - * - * @return bool - */ - public function isNotEmpty() - { - return ! $this->isEmpty(); - } - - /** - * Run a map over each nested chunk of items. - * - * @template TMapSpreadValue - * - * @param callable(mixed...): TMapSpreadValue $callback - * @return static - */ - public function mapSpread(callable $callback) - { - return $this->map(function ($chunk, $key) use ($callback) { - $chunk[] = $key; - - return $callback(...$chunk); - }); - } - - /** - * Run a grouping map over the items. - * - * The callback should return an associative array with a single key/value pair. - * - * @template TMapToGroupsKey of array-key - * @template TMapToGroupsValue - * - * @param callable(TValue, TKey): array $callback - * @return static> - */ - public function mapToGroups(callable $callback) - { - $groups = $this->mapToDictionary($callback); - - return $groups->map($this->make(...)); - } - - /** - * Map a collection and flatten the result by a single level. - * - * @template TFlatMapKey of array-key - * @template TFlatMapValue - * - * @param callable(TValue, TKey): (\Illuminate\Support\Collection|array) $callback - * @return static - */ - public function flatMap(callable $callback) - { - return $this->map($callback)->collapse(); - } - - /** - * Map the values into a new class. - * - * @template TMapIntoValue - * - * @param class-string $class - * @return static - */ - public function mapInto($class) - { - if (is_subclass_of($class, BackedEnum::class)) { - return $this->map(fn ($value, $key) => $class::from($value)); - } - - return $this->map(fn ($value, $key) => new $class($value, $key)); - } - - /** - * Get the min value of a given key. - * - * @template TMinResult = mixed - * - * @param (callable(TValue): TMinResult)|string|null $callback - * @return ($callback is callable ? ?TMinResult : ($callback is null ? ?TValue : mixed)) - */ - public function min($callback = null) - { - $callback = $this->valueRetriever($callback); - - return $this->map(fn ($value) => $callback($value)) - ->reject(fn ($value) => is_null($value)) - ->reduce(fn ($result, $value) => is_null($result) || $value < $result ? $value : $result); - } - - /** - * Get the max value of a given key. - * - * @template TMaxResult = mixed - * - * @param (callable(TValue): TMaxResult)|string|null $callback - * @return ($callback is callable ? ?TMaxResult : ($callback is null ? ?TValue : mixed)) - */ - public function max($callback = null) - { - $callback = $this->valueRetriever($callback); - - return $this->reject(fn ($value) => is_null($value))->reduce(function ($result, $item) use ($callback) { - $value = $callback($item); - - return is_null($result) || $value > $result ? $value : $result; - }); - } - - /** - * "Paginate" the collection by slicing it into a smaller collection. - * - * @param int $page - * @param int $perPage - * @return static - */ - public function forPage($page, $perPage) - { - $offset = max(0, ($page - 1) * $perPage); - - return $this->slice($offset, $perPage); - } - - /** - * Partition the collection into two arrays using the given callback or key. - * - * @param (callable(TValue, TKey): bool)|TValue|string $key - * @param mixed $operator - * @param mixed $value - * @return static, static> - */ - public function partition($key, $operator = null, $value = null) - { - $callback = func_num_args() === 1 - ? $this->valueRetriever($key) - : $this->operatorForWhere(...func_get_args()); - - [$passed, $failed] = Arr::partition($this->getIterator(), $callback); - - return $this->newInstance([$this->newInstance($passed), $this->newInstance($failed)]); - } - - /** - * Calculate the percentage of items that pass a given truth test. - * - * @param (callable(TValue, TKey): bool) $callback - * @param int $precision - * @return float|null - */ - public function percentage(callable $callback, int $precision = 2) - { - if ($this->isEmpty()) { - return null; - } - - return round( - $this->filter($callback)->count() / $this->count() * 100, - $precision - ); - } - - /** - * Get the sum of the given values. - * - * @template TReturnType - * - * @param (callable(TValue, TKey): TReturnType)|string|null $callback - * @return ($callback is callable ? TReturnType : mixed) - */ - public function sum($callback = null) - { - $callback = is_null($callback) - ? $this->identity() - : $this->valueRetriever($callback); - - return $this->reduce(fn ($result, $item, $key) => $result + $callback($item, $key), 0); - } - - /** - * Apply the callback if the collection is empty. - * - * @template TWhenEmptyReturnType - * - * @param (callable($this): TWhenEmptyReturnType) $callback - * @param (callable($this): TWhenEmptyReturnType)|null $default - * @return $this|TWhenEmptyReturnType - */ - public function whenEmpty(callable $callback, ?callable $default = null) - { - return $this->when($this->isEmpty(), $callback, $default); - } - - /** - * Apply the callback if the collection is not empty. - * - * @template TWhenNotEmptyReturnType - * - * @param callable($this): TWhenNotEmptyReturnType $callback - * @param (callable($this): TWhenNotEmptyReturnType)|null $default - * @return $this|TWhenNotEmptyReturnType - */ - public function whenNotEmpty(callable $callback, ?callable $default = null) - { - return $this->when($this->isNotEmpty(), $callback, $default); - } - - /** - * Apply the callback unless the collection is empty. - * - * @template TUnlessEmptyReturnType - * - * @param callable($this): TUnlessEmptyReturnType $callback - * @param (callable($this): TUnlessEmptyReturnType)|null $default - * @return $this|TUnlessEmptyReturnType - */ - public function unlessEmpty(callable $callback, ?callable $default = null) - { - return $this->whenNotEmpty($callback, $default); - } - - /** - * Apply the callback unless the collection is not empty. - * - * @template TUnlessNotEmptyReturnType - * - * @param callable($this): TUnlessNotEmptyReturnType $callback - * @param (callable($this): TUnlessNotEmptyReturnType)|null $default - * @return $this|TUnlessNotEmptyReturnType - */ - public function unlessNotEmpty(callable $callback, ?callable $default = null) - { - return $this->whenEmpty($callback, $default); - } - - /** - * Filter items by the given key value pair. - * - * @param callable|string $key - * @param mixed $operator - * @param mixed $value - * @return static - */ - public function where($key, $operator = null, $value = null) - { - return $this->filter($this->operatorForWhere(...func_get_args())); - } - - /** - * Filter items where the value for the given key is null. - * - * @param string|null $key - * @return static - */ - public function whereNull($key = null) - { - return $this->whereStrict($key, null); - } - - /** - * Filter items where the value for the given key is not null. - * - * @param string|null $key - * @return static - */ - public function whereNotNull($key = null) - { - return $this->where($key, '!==', null); - } - - /** - * Filter items by the given key value pair using strict comparison. - * - * @param string $key - * @param mixed $value - * @return static - */ - public function whereStrict($key, $value) - { - return $this->where($key, '===', $value); - } - - /** - * Filter items by the given key value pair. - * - * @param string $key - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @param bool $strict - * @return static - */ - public function whereIn($key, $values, $strict = false) - { - $values = $this->getArrayableItems($values); - - return $this->filter(fn ($item) => in_array(data_get($item, $key), $values, $strict)); - } - - /** - * Filter items by the given key value pair using strict comparison. - * - * @param string $key - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @return static - */ - public function whereInStrict($key, $values) - { - return $this->whereIn($key, $values, true); - } - - /** - * Filter items such that the value of the given key is between the given values. - * - * @param string $key - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @return static - */ - public function whereBetween($key, $values) - { - return $this->where($key, '>=', reset($values))->where($key, '<=', end($values)); - } - - /** - * Filter items such that the value of the given key is not between the given values. - * - * @param string $key - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @return static - */ - public function whereNotBetween($key, $values) - { - return $this->filter( - fn ($item) => data_get($item, $key) < reset($values) || data_get($item, $key) > end($values) - ); - } - - /** - * Filter items by the given key value pair. - * - * @param string $key - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @param bool $strict - * @return static - */ - public function whereNotIn($key, $values, $strict = false) - { - $values = $this->getArrayableItems($values); - - return $this->reject(fn ($item) => in_array(data_get($item, $key), $values, $strict)); - } - - /** - * Filter items by the given key value pair using strict comparison. - * - * @param string $key - * @param \Illuminate\Contracts\Support\Arrayable|iterable $values - * @return static - */ - public function whereNotInStrict($key, $values) - { - return $this->whereNotIn($key, $values, true); - } - - /** - * Filter the items, removing any items that don't match the given type(s). - * - * @template TWhereInstanceOf - * - * @param class-string|array> $type - * @return static - */ - public function whereInstanceOf($type) - { - return $this->filter(function ($value) use ($type) { - if (is_array($type)) { - return array_any($type, fn ($classType) => $value instanceof $classType); - } - - return $value instanceof $type; - }); - } - - /** - * Pass the collection to the given callback and return the result. - * - * @template TPipeReturnType - * - * @param callable($this): TPipeReturnType $callback - * @return TPipeReturnType - */ - public function pipe(callable $callback) - { - return $callback($this); - } - - /** - * Pass the collection into a new class. - * - * @template TPipeIntoValue - * - * @param class-string $class - * @return TPipeIntoValue - */ - public function pipeInto($class) - { - return new $class($this); - } - - /** - * Pass the collection through a series of callable pipes and return the result. - * - * @param array $callbacks - * @return mixed - */ - public function pipeThrough($callbacks) - { - return (new Collection($callbacks))->reduce( - fn ($carry, $callback) => $callback($carry), - $this, - ); - } - - /** - * Reduce the collection to a single value. - * - * @template TReduceInitial - * @template TReduceReturnType - * - * @param callable(TReduceInitial|TReduceReturnType, TValue, TKey): TReduceReturnType $callback - * @param TReduceInitial $initial - * @return TReduceInitial|TReduceReturnType - */ - public function reduce(callable $callback, $initial = null) - { - $result = $initial; - - foreach ($this as $key => $value) { - $result = $callback($result, $value, $key); - } - - return $result; - } - - /** - * Reduce the collection to a single value by mutating an initial value. - * - * @template TReduceIntoInitial - * - * @param TReduceIntoInitial $initial - * @param callable(TReduceIntoInitial, TValue, TKey): void $callback - * @return TReduceIntoInitial - */ - public function reduceInto($initial, callable $callback) - { - foreach ($this as $key => $value) { - $callback($initial, $value, $key); - } - - return $initial; - } - - /** - * Reduce the collection to multiple aggregate values. - * - * @param callable $callback - * @param mixed ...$initial - * @return array - * - * @throws \UnexpectedValueException - */ - public function reduceSpread(callable $callback, ...$initial) - { - $result = $initial; - - foreach ($this as $key => $value) { - $result = call_user_func_array($callback, array_merge($result, [$value, $key])); - - if (! is_array($result)) { - throw new UnexpectedValueException(sprintf( - "%s::reduceSpread expects reducer to return an array, but got a '%s' instead.", - class_basename(static::class), gettype($result) - )); - } - } - - return $result; - } - - /** - * Reduce an associative collection to a single value. - * - * @template TReduceWithKeysInitial - * @template TReduceWithKeysReturnType - * - * @param callable(TReduceWithKeysInitial|TReduceWithKeysReturnType, TValue, TKey): TReduceWithKeysReturnType $callback - * @param TReduceWithKeysInitial $initial - * @return TReduceWithKeysInitial|TReduceWithKeysReturnType - */ - public function reduceWithKeys(callable $callback, $initial = null) - { - return $this->reduce($callback, $initial); - } - - /** - * Create a collection of all elements that do not pass a given truth test. - * - * @param (callable(TValue, TKey): bool)|bool|TValue $callback - * @return static - */ - public function reject($callback = true) - { - $useAsCallable = $this->useAsCallable($callback); - - return $this->filter(function ($value, $key) use ($callback, $useAsCallable) { - return $useAsCallable - ? ! $callback($value, $key) - : $value != $callback; - }); - } - - /** - * Chunk the collection into chunks by comparing adjacent values using the given key or callback. - * - * @param (callable(TValue, TKey): mixed)|string $key - * @return static> - */ - public function chunkBy($key) - { - $callback = $this->valueRetriever($key); - - return $this->chunkWhile( - fn ($value, $key, $chunk) => $callback($value, $key) == $callback($chunk->last(), $chunk->keys()->last()) - ); - } - - /** - * Pass the collection to the given callback and then return it. - * - * @param callable($this): mixed $callback - * @return $this - */ - public function tap(callable $callback) - { - $callback($this); - - return $this; - } - - /** - * Return only unique items from the collection array. - * - * @param (callable(TValue, TKey): mixed)|string|null $key - * @param bool $strict - * @return static - */ - public function unique($key = null, $strict = false) - { - $callback = $this->valueRetriever($key); - - $exists = []; - - return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) { - if (in_array($id = $callback($item, $key), $exists, $strict)) { - return true; - } - - $exists[] = $id; - }); - } - - /** - * Return only unique items from the collection array using strict comparison. - * - * @param (callable(TValue, TKey): mixed)|string|null $key - * @return static - */ - public function uniqueStrict($key = null) - { - return $this->unique($key, true); - } - - /** - * Collect the values into a collection. - * - * @return \Illuminate\Support\Collection - */ - public function collect() - { - return new Collection($this->all()); - } - - /** - * Get the collection of items as a plain array. - * - * @return array - */ - public function toArray() - { - return $this->map(fn ($value) => $value instanceof Arrayable ? $value->toArray() : $value)->all(); - } - - /** - * Convert the object into something JSON serializable. - * - * @return array - */ - public function jsonSerialize(): array - { - return array_map(function ($value) { - return match (true) { - $value instanceof JsonSerializable => $value->jsonSerialize(), - $value instanceof Jsonable => json_decode($value->toJson(), true), - $value instanceof Arrayable => $value->toArray(), - default => $value, - }; - }, $this->all()); - } - - /** - * Get the collection of items as JSON. - * - * @param int $options - * @return string - */ - public function toJson($options = 0) - { - return json_encode($this->jsonSerialize(), $options); - } - - /** - * Get the collection of items as pretty print formatted JSON. - * - * @param int $options - * @return string - */ - public function toPrettyJson(int $options = 0) - { - return $this->toJson(JSON_PRETTY_PRINT | $options); - } - - /** - * Get a CachingIterator instance. - * - * @param int $flags - * @return \CachingIterator - */ - public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING) - { - return new CachingIterator($this->getIterator(), $flags); - } - - /** - * Convert the collection to its string representation. - * - * @return string - */ - public function __toString() - { - return $this->escapeWhenCastingToString - ? e($this->toJson()) - : $this->toJson(); - } - - /** - * Indicate that the model's string representation should be escaped when __toString is invoked. - * - * @param bool $escape - * @return $this - */ - public function escapeWhenCastingToString($escape = true) - { - $this->escapeWhenCastingToString = $escape; - - return $this; - } - - /** - * Add a method to the list of proxied methods. - * - * @param string $method - * @return void - */ - public static function proxy($method) - { - static::$proxies[] = $method; - } - - /** - * Dynamically access collection proxies. - * - * @param string $key - * @return mixed - * - * @throws \Exception - */ - public function __get($key) - { - if (! in_array($key, static::$proxies)) { - throw new Exception("Property [{$key}] does not exist on this collection instance."); - } - - return new HigherOrderCollectionProxy($this, $key); - } - - /** - * Results array of items from Collection or Arrayable. - * - * @param mixed $items - * @return array - */ - protected function getArrayableItems($items) - { - return is_null($items) || is_scalar($items) || $items instanceof UnitEnum - ? Arr::wrap($items) - : Arr::from($items); - } - - /** - * Get an operator checker callback. - * - * @param callable|string $key - * @param string|null $operator - * @param mixed $value - * @return \Closure - */ - protected function operatorForWhere($key, $operator = null, $value = null) - { - if ($this->useAsCallable($key)) { - return $key; - } - - if (func_num_args() === 1) { - $value = true; - - $operator = '='; - } - - if (func_num_args() === 2) { - $value = $operator; - - $operator = '='; - } - - return function ($item) use ($key, $operator, $value) { - $retrieved = enum_value(data_get($item, $key)); - $value = enum_value($value); - - $strings = array_filter([$retrieved, $value], function ($value) { - return match (true) { - is_string($value) => true, - $value instanceof \Stringable => true, - default => false, - }; - }); - - if (count($strings) < 2 && count(array_filter([$retrieved, $value], 'is_object')) == 1) { - return in_array($operator, ['!=', '<>', '!==']); - } - - switch ($operator) { - default: - case '=': - case '==': return $retrieved == $value; - case '!=': - case '<>': return $retrieved != $value; - case '<': return $retrieved < $value; - case '>': return $retrieved > $value; - case '<=': return $retrieved <= $value; - case '>=': return $retrieved >= $value; - case '===': return $retrieved === $value; - case '!==': return $retrieved !== $value; - case '<=>': return $retrieved <=> $value; - } - }; - } - - /** - * Determine if the given value is callable, but not a string. - * - * @param mixed $value - * @return bool - */ - protected function useAsCallable($value) - { - return ! is_string($value) && is_callable($value); - } - - /** - * Get a value retrieving callback. - * - * @param callable|string|null $value - * @return callable - */ - protected function valueRetriever($value) - { - if ($this->useAsCallable($value)) { - return $value; - } - - return fn ($item) => data_get($item, $value); - } - - /** - * Make a function to check an item's equality. - * - * @param mixed $value - * @return \Closure(mixed): bool - */ - protected function equality($value) - { - return fn ($item) => $item === $value; - } - - /** - * Make a function using another function, by negating its result. - * - * @param \Closure $callback - * @return \Closure - */ - protected function negate(Closure $callback) - { - return fn (...$params) => ! $callback(...$params); - } - - /** - * Make a function that returns what's passed to it. - * - * @return \Closure(TValue): TValue - */ - protected function identity() - { - return fn ($value) => $value; - } -} diff --git a/src/Illuminate/Support/Traits/Macroable.php b/src/Illuminate/Support/Traits/Macroable.php deleted file mode 100644 index 2ee06e177..000000000 --- a/src/Illuminate/Support/Traits/Macroable.php +++ /dev/null @@ -1,134 +0,0 @@ -getMethods( - ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED - ); - - foreach ($methods as $method) { - if ($replace || ! static::hasMacro($method->name)) { - static::macro($method->name, $method->invoke($mixin)); - } - } - } - - /** - * Checks if macro is registered. - * - * @param string $name - * @return bool - */ - public static function hasMacro($name) - { - return isset(static::$macros[$name]); - } - - /** - * Flush the existing macros. - * - * @return void - */ - public static function flushMacros() - { - static::$macros = []; - } - - /** - * Dynamically handle calls to the class. - * - * @param string $method - * @param array $parameters - * @return mixed - * - * @throws \BadMethodCallException - */ - public static function __callStatic($method, $parameters) - { - if (! static::hasMacro($method)) { - throw new BadMethodCallException(sprintf( - 'Method %s::%s does not exist.', static::class, $method - )); - } - - $macro = static::$macros[$method]; - - if ($macro instanceof Closure) { - $macro = $macro->bindTo(null, static::class); - } - - return $macro(...$parameters); - } - - /** - * Dynamically handle calls to the class. - * - * @param string $method - * @param array $parameters - * @return mixed - * - * @throws \BadMethodCallException - */ - public function __call($method, $parameters) - { - if (! static::hasMacro($method)) { - throw new BadMethodCallException(sprintf( - 'Method %s::%s does not exist.', static::class, $method - )); - } - - $macro = static::$macros[$method]; - - if ($macro instanceof Closure) { - try { - $macro = $macro->bindTo($this, static::class) ?? throw new RuntimeException; - } catch (Throwable) { - $macro = $macro->bindTo(null, static::class); - } - } - - return $macro(...$parameters); - } -} diff --git a/src/Illuminate/Support/helpers.php b/src/Illuminate/Support/helpers.php index d2eb33290..560bc9fe0 100755 --- a/src/Illuminate/Support/helpers.php +++ b/src/Illuminate/Support/helpers.php @@ -105,7 +105,16 @@ function array_add($array, $key, $value) */ function array_build($array, Closure $callback) { - return Arr::build($array, $callback); + $results = array(); + + foreach ($array as $key => $value) + { + [$innerKey, $innerValue] = call_user_func($callback, $key, $value); + + $results[$innerKey] = $innerValue; + } + + return $results; } } @@ -164,7 +173,22 @@ function array_except($array, $keys) */ function array_fetch($array, $key) { - return Arr::fetch($array, $key); + foreach (explode('.', $key) as $segment) + { + $results = array(); + + foreach ($array as $value) + { + if (array_key_exists($segment, $value = (array) $value)) + { + $results[] = $value[$segment]; + } + } + + $array = array_values($results); + } + + return array_values($results); } } @@ -417,7 +441,7 @@ function csrf_token() if (isset($session)) { - return $session->getToken(); + return $session->token(); } throw new RuntimeException("Application session store not set."); diff --git a/src/Illuminate/Translation/TranslationServiceProvider.php b/src/Illuminate/Translation/TranslationServiceProvider.php index 4b696501d..e508e2eb6 100755 --- a/src/Illuminate/Translation/TranslationServiceProvider.php +++ b/src/Illuminate/Translation/TranslationServiceProvider.php @@ -20,7 +20,7 @@ public function register() { $this->registerLoader(); - $this->app->bindShared('translator', function($app) + $this->app->singleton('translator', function($app) { $loader = $app['translation.loader']; @@ -44,7 +44,7 @@ public function register() */ protected function registerLoader() { - $this->app->bindShared('translation.loader', function($app) + $this->app->singleton('translation.loader', function($app) { return new FileLoader($app['files'], $app['path'].'/lang'); }); diff --git a/src/Illuminate/Validation/ValidationServiceProvider.php b/src/Illuminate/Validation/ValidationServiceProvider.php index b6b2dbdd7..3c1ab1b71 100755 --- a/src/Illuminate/Validation/ValidationServiceProvider.php +++ b/src/Illuminate/Validation/ValidationServiceProvider.php @@ -20,7 +20,7 @@ public function register() { $this->registerPresenceVerifier(); - $this->app->bindShared('validator', function($app) + $this->app->singleton('validator', function($app) { $validator = new Factory($app['translator'], $app); @@ -43,7 +43,7 @@ public function register() */ protected function registerPresenceVerifier() { - $this->app->bindShared('validation.presence', function($app) + $this->app->singleton('validation.presence', function($app) { return new DatabasePresenceVerifier($app['db']); }); diff --git a/src/Illuminate/View/View.php b/src/Illuminate/View/View.php index 5a33e7e28..e76a4aefc 100755 --- a/src/Illuminate/View/View.php +++ b/src/Illuminate/View/View.php @@ -5,7 +5,7 @@ use Illuminate\Contracts\Support\Renderable; use Illuminate\Support\MessageBag; use Illuminate\View\Engines\EngineInterface; -use Illuminate\Support\Contracts\MessageProviderInterface; +use Illuminate\Contracts\Support\MessageProvider as MessageProviderInterface; use Illuminate\Support\Contracts\ArrayableInterface as Arrayable; class View implements ArrayAccess, Renderable diff --git a/src/Illuminate/View/ViewServiceProvider.php b/src/Illuminate/View/ViewServiceProvider.php index e186da87f..7763b869f 100755 --- a/src/Illuminate/View/ViewServiceProvider.php +++ b/src/Illuminate/View/ViewServiceProvider.php @@ -35,7 +35,7 @@ public function register() */ public function registerEngineResolver() { - $this->app->bindShared('view.engine.resolver', function() + $this->app->singleton('view.engine.resolver', function() { $resolver = new EngineResolver; @@ -75,7 +75,7 @@ public function registerBladeEngine($resolver) // The Compiler engine requires an instance of the CompilerInterface, which in // this case will be the Blade compiler, so we'll first create the compiler // instance to pass into the engine so it can compile the views properly. - $app->bindShared('blade.compiler', function($app) + $app->singleton('blade.compiler', function($app) { $cache = $app['path.storage'].'/views'; @@ -95,7 +95,7 @@ public function registerBladeEngine($resolver) */ public function registerViewFinder() { - $this->app->bindShared('view.finder', function($app) + $this->app->singleton('view.finder', function($app) { $paths = $app['config']['view.paths']; @@ -110,7 +110,7 @@ public function registerViewFinder() */ public function registerFactory() { - $this->app->bindShared('view', function($app) + $this->app->singleton('view', function($app) { // Next we need to grab the engine resolver instance that will be used by the // environment. The resolver will be used by an environment to get each of diff --git a/src/Illuminate/Workbench/Console/WorkbenchMakeCommand.php b/src/Illuminate/Workbench/Console/WorkbenchMakeCommand.php index 5a32cb988..37295961b 100755 --- a/src/Illuminate/Workbench/Console/WorkbenchMakeCommand.php +++ b/src/Illuminate/Workbench/Console/WorkbenchMakeCommand.php @@ -47,7 +47,7 @@ public function __construct(PackageCreator $creator) * * @return void */ - public function fire() + public function handle() { $workbench = $this->runCreator($this->buildPackage()); diff --git a/src/Illuminate/Workbench/WorkbenchServiceProvider.php b/src/Illuminate/Workbench/WorkbenchServiceProvider.php index 4dcd4e25c..d2e41e826 100755 --- a/src/Illuminate/Workbench/WorkbenchServiceProvider.php +++ b/src/Illuminate/Workbench/WorkbenchServiceProvider.php @@ -19,12 +19,12 @@ class WorkbenchServiceProvider extends ServiceProvider { */ public function register() { - $this->app->bindShared('package.creator', function($app) + $this->app->singleton('package.creator', function($app) { return new PackageCreator($app['files']); }); - $this->app->bindShared('command.workbench', function($app) + $this->app->singleton('command.workbench', function($app) { return new WorkbenchMakeCommand($app['package.creator']); }); diff --git a/tests/Cache/CacheApcStoreTest.php b/tests/Cache/CacheApcStoreTest.php deleted file mode 100755 index ac3d28a26..000000000 --- a/tests/Cache/CacheApcStoreTest.php +++ /dev/null @@ -1,70 +0,0 @@ -getMock(ApcWrapper::class, ['get']); - $apc->expects($this->once())->method('get')->with($this->equalTo('foobar'))->willReturn(null); - $store = new Illuminate\Cache\ApcStore($apc, 'foo'); - $this->assertNull($store->get('bar')); - } - - - public function testAPCValueIsReturned() - { - $apc = $this->getMock(ApcWrapper::class, ['get']); - $apc->expects($this->once())->method('get')->willReturn('bar'); - $store = new Illuminate\Cache\ApcStore($apc); - $this->assertEquals('bar', $store->get('foo')); - } - - - public function testSetMethodProperlyCallsAPC() - { - $apc = $this->getMock(ApcWrapper::class, ['put']); - $apc->expects($this->once())->method('put')->with($this->equalTo('foo'), $this->equalTo('bar'), $this->equalTo(60)); - $store = new Illuminate\Cache\ApcStore($apc); - $store->put('foo', 'bar', 1); - } - - - public function testIncrementMethodProperlyCallsAPC() - { - $apc = $this->getMock(ApcWrapper::class, ['increment']); - $apc->expects($this->once())->method('increment')->with($this->equalTo('foo'), $this->equalTo(5)); - $store = new Illuminate\Cache\ApcStore($apc); - $store->increment('foo', 5); - } - - - public function testDecrementMethodProperlyCallsAPC() - { - $apc = $this->getMock(ApcWrapper::class, ['decrement']); - $apc->expects($this->once())->method('decrement')->with($this->equalTo('foo'), $this->equalTo(5)); - $store = new Illuminate\Cache\ApcStore($apc); - $store->decrement('foo', 5); - } - - - public function testStoreItemForeverProperlyCallsAPC() - { - $apc = $this->getMock(ApcWrapper::class, ['put']); - $apc->expects($this->once())->method('put')->with($this->equalTo('foo'), $this->equalTo('bar'), $this->equalTo(0)); - $store = new Illuminate\Cache\ApcStore($apc); - $store->forever('foo', 'bar'); - } - - - public function testForgetMethodProperlyCallsAPC() - { - $apc = $this->getMock(ApcWrapper::class, ['delete']); - $apc->expects($this->once())->method('delete')->with($this->equalTo('foo')); - $store = new Illuminate\Cache\ApcStore($apc); - $store->forget('foo'); - } - -} diff --git a/tests/Cache/CacheArrayStoreTest.php b/tests/Cache/CacheArrayStoreTest.php deleted file mode 100755 index fd03da61f..000000000 --- a/tests/Cache/CacheArrayStoreTest.php +++ /dev/null @@ -1,68 +0,0 @@ -put('foo', 'bar', 10); - $this->assertEquals('bar', $store->get('foo')); - } - - - public function testStoreItemForeverProperlyStoresInArray() - { - $mock = $this->getMock(ArrayStore::class, ['put']); - $mock->expects($this->once())->method('put')->with($this->equalTo('foo'), $this->equalTo('bar'), $this->equalTo(0)); - $mock->forever('foo', 'bar'); - } - - - public function testValuesCanBeIncremented() - { - $store = new ArrayStore; - $store->put('foo', 1, 10); - $store->increment('foo'); - $this->assertEquals(2, $store->get('foo')); - } - - - public function testValuesCanBeDecremented() - { - $store = new ArrayStore; - $store->put('foo', 1, 10); - $store->decrement('foo'); - $this->assertEquals(0, $store->get('foo')); - } - - - public function testItemsCanBeRemoved() - { - $store = new ArrayStore; - $store->put('foo', 'bar', 10); - $store->forget('foo'); - $this->assertNull($store->get('foo')); - } - - - public function testItemsCanBeFlushed() - { - $store = new ArrayStore; - $store->put('foo', 'bar', 10); - $store->put('baz', 'boom', 10); - $store->flush(); - $this->assertNull($store->get('foo')); - $this->assertNull($store->get('baz')); - } - - - public function testCacheKey() - { - $store = new ArrayStore; - $this->assertEquals('', $store->getPrefix()); - } - -} diff --git a/tests/Cache/CacheDatabaseStoreTest.php b/tests/Cache/CacheDatabaseStoreTest.php deleted file mode 100755 index c81b9e43d..000000000 --- a/tests/Cache/CacheDatabaseStoreTest.php +++ /dev/null @@ -1,131 +0,0 @@ -getStore(); - $table = m::mock('StdClass'); - $store->getConnection()->shouldReceive('table')->once()->with('table')->andReturn($table); - $table->shouldReceive('where')->once()->with('key', '=', 'prefixfoo')->andReturn($table); - $table->shouldReceive('first')->once()->andReturn(null); - - $this->assertNull($store->get('foo')); - } - - - public function testNullIsReturnedAndItemDeletedWhenItemIsExpired(): void - { - $store = $this->getMock(DatabaseStore::class, ['forget'], $this->getMocks()); - $table = m::mock('StdClass'); - $store->getConnection()->shouldReceive('table')->once()->with('table')->andReturn($table); - $table->shouldReceive('where')->once()->with('key', '=', 'prefixfoo')->andReturn($table); - $table->shouldReceive('first')->once()->andReturn((object) ['expiration' => 1]); - $store->expects($this->once())->method('forget')->with($this->equalTo('foo'))->willReturn(null); - - $this->assertNull($store->get('foo')); - } - - - public function testDecryptedValueIsReturnedWhenItemIsValid(): void - { - $store = $this->getStore(); - $table = m::mock('StdClass'); - $store->getConnection()->shouldReceive('table')->once()->with('table')->andReturn($table); - $table->shouldReceive('where')->once()->with('key', '=', 'prefixfoo')->andReturn($table); - $table->shouldReceive('first')->once()->andReturn((object) ['value' => 'bar', 'expiration' => 999999999999999]); - $store->getEncrypter()->shouldReceive('decrypt')->once()->with('bar')->andReturn('bar'); - - $this->assertEquals('bar', $store->get('foo')); - } - - - public function testEncryptedValueIsInsertedWhenNoExceptionsAreThrown(): void - { - $store = $this->getMock(DatabaseStore::class, ['getTime'], $this->getMocks()); - $table = m::mock('StdClass'); - $store->getConnection()->shouldReceive('table')->once()->with('table')->andReturn($table); - $store->getEncrypter()->shouldReceive('encrypt')->once()->with('bar')->andReturn('bar'); - $store->expects($this->once())->method('getTime')->willReturn(1); - $table->shouldReceive('insert')->once()->with(['key' => 'prefixfoo', 'value' => 'bar', 'expiration' => 61]); - - $store->put('foo', 'bar', 1); - } - - - public function testEncryptedValueIsUpdatedWhenInsertThrowsException(): void - { - $store = $this->getMock(DatabaseStore::class, ['getTime'], $this->getMocks()); - $table = m::mock('StdClass'); - $store->getConnection()->shouldReceive('table')->with('table')->andReturn($table); - $store->getEncrypter()->shouldReceive('encrypt')->once()->with('bar')->andReturn('bar'); - $store->expects($this->once())->method('getTime')->willReturn(1); - $table->shouldReceive('insert')->once()->with(['key' => 'prefixfoo', 'value' => 'bar', 'expiration' => 61])->andReturnUsing(function(): never - { - throw new Exception; - }); - $table->shouldReceive('where')->once()->with('key', '=', 'prefixfoo')->andReturn($table); - $table->shouldReceive('update')->once()->with(['value' => 'bar', 'expiration' => 61]); - - $store->put('foo', 'bar', 1); - } - - - public function testForeverCallsStoreItemWithReallyLongTime(): void - { - $store = $this->getMock(DatabaseStore::class, ['put'], $this->getMocks()); - $store->expects($this->once())->method('put')->with($this->equalTo('foo'), $this->equalTo('bar'), $this->equalTo(5256000)); - $store->forever('foo', 'bar'); - } - - - public function testItemsMayBeRemovedFromCache(): void - { - $store = $this->getStore(); - $table = m::mock('StdClass'); - $store->getConnection()->shouldReceive('table')->once()->with('table')->andReturn($table); - $table->shouldReceive('where')->once()->with('key', '=', 'prefixfoo')->andReturn($table); - $table->shouldReceive('delete')->once(); - - $store->forget('foo'); - } - - - public function testItemsMayBeFlushedFromCache(): void - { - $store = $this->getStore(); - $table = m::mock('StdClass'); - $store->getConnection()->shouldReceive('table')->once()->with('table')->andReturn($table); - $table->shouldReceive('delete')->once(); - - $store->flush(); - } - - - protected function getStore(): DatabaseStore - { - return new DatabaseStore(m::mock(Connection::class), m::mock( - Encrypter::class - ), 'table', 'prefix'); - } - - - protected function getMocks(): array - { - return [m::mock(Connection::class), m::mock(Encrypter::class), 'table', 'prefix']; - } - -} diff --git a/tests/Cache/CacheFileStoreTest.php b/tests/Cache/CacheFileStoreTest.php deleted file mode 100755 index 9b8f96bd5..000000000 --- a/tests/Cache/CacheFileStoreTest.php +++ /dev/null @@ -1,146 +0,0 @@ -mockFilesystem(); - $files->expects($this->once())->method('exists')->willReturn(false); - $store = new FileStore($files, __DIR__); - $value = $store->get('foo'); - $this->assertNull($value); - } - - - public function testPutCreatesMissingDirectories() - { - $files = $this->mockFilesystem(); - $md5 = md5('foo'); - $full_dir = __DIR__.'/'.substr($md5, 0, 2).'/'.substr($md5, 2, 2); - $files->expects($this->once())->method('makeDirectory')->with($this->equalTo($full_dir), $this->equalTo(0777), $this->equalTo(true)); - $files->expects($this->once())->method('put')->with($this->equalTo($full_dir.'/'.$md5)); - $store = new FileStore($files, __DIR__); - $store->put('foo', '0000000000', 0); - } - - - public function testExpiredItemsReturnNull() - { - $files = $this->mockFilesystem(); - $files->expects($this->once())->method('exists')->willReturn(true); - $contents = '0000000000'; - $files->expects($this->once())->method('get')->willReturn($contents); - $store = $this->getMock(FileStore::class, ['forget'], [$files, __DIR__]); - $store->expects($this->once())->method('forget'); - $value = $store->get('foo'); - $this->assertNull($value); - } - - - public function testValidItemReturnsContents() - { - $files = $this->mockFilesystem(); - $files->expects($this->once())->method('exists')->willReturn(true); - $contents = '9999999999'.serialize('Hello World'); - $files->expects($this->once())->method('get')->willReturn($contents); - $store = new FileStore($files, __DIR__); - $this->assertEquals('Hello World', $store->get('foo')); - } - - - public function testStoreItemProperlyStoresValues() - { - $files = $this->mockFilesystem(); - $store = $this->getMock(FileStore::class, ['expiration'], [$files, __DIR__]); - $store->expects($this->once())->method('expiration')->with($this->equalTo(10))->willReturn(1111111111); - $contents = '1111111111'.serialize('Hello World'); - $md5 = md5('foo'); - $cache_dir = substr($md5, 0, 2).'/'.substr($md5, 2, 2); - $files->expects($this->once())->method('put')->with($this->equalTo(__DIR__.'/'.$cache_dir.'/'.$md5), $this->equalTo($contents)); - $store->put('foo', 'Hello World', 10); - } - - - public function testForeversAreStoredWithHighTimestamp() - { - $files = $this->mockFilesystem(); - $contents = '9999999999'.serialize('Hello World'); - $md5 = md5('foo'); - $cache_dir = substr($md5, 0, 2).'/'.substr($md5, 2, 2); - $files->expects($this->once())->method('put')->with($this->equalTo(__DIR__.'/'.$cache_dir.'/'.$md5), $this->equalTo($contents)); - $store = new FileStore($files, __DIR__); - $store->forever('foo', 'Hello World', 10); - } - - - public function testRemoveDeletesFileDoesntExist() - { - $files = $this->mockFilesystem(); - $md5 = md5('foobull'); - $cache_dir = substr($md5, 0, 2).'/'.substr($md5, 2, 2); - $files->expects($this->once())->method('exists')->with($this->equalTo(__DIR__.'/'.$cache_dir.'/'.$md5))->willReturn( - false - ); - $store = new FileStore($files, __DIR__); - $store->forget('foobull'); - } - - - public function testRemoveDeletesFile() - { - $files = $this->mockFilesystem(); - $md5 = md5('foobar'); - $cache_dir = substr($md5, 0, 2).'/'.substr($md5, 2, 2); - $store = new FileStore($files, __DIR__); - $store->put('foobar', 'Hello Baby', 10); - $files->expects($this->once())->method('exists')->with($this->equalTo(__DIR__.'/'.$cache_dir.'/'.$md5))->willReturn( - true - ); - $files->expects($this->once())->method('delete')->with($this->equalTo(__DIR__.'/'.$cache_dir.'/'.$md5)); - $store->forget('foobar'); - } - - - public function testFlushCleansDirectory() - { - $files = $this->mockFilesystem(); - $files->expects($this->once())->method('isDirectory')->with($this->equalTo(__DIR__))->willReturn(true); - $files->expects($this->once())->method('directories')->with($this->equalTo(__DIR__))->willReturn(['foo']); - $files->expects($this->once())->method('deleteDirectory')->with($this->equalTo('foo')); - - $store = new FileStore($files, __DIR__); - $store->flush(); - } - - - public function testFlushIgnoreNonExistingDirectory() - { - $files = $this->mockFilesystem(); - $files->expects($this->once())->method('isDirectory')->with($this->equalTo(__DIR__ . '--wrong'))->willReturn( - false - ); - - $store = new FileStore($files, __DIR__ . '--wrong'); - $store->flush(); - } - - - protected function mockFilesystem() - { - return $this->getMock(Filesystem::class, [ - 'get', - 'put', - 'exists', - 'delete', - 'directories', - 'isDirectory', - 'makeDirectory', - 'deleteDirectory' - ]); - } - -} diff --git a/tests/Cache/CacheMemcachedConnectorTest.php b/tests/Cache/CacheMemcachedConnectorTest.php deleted file mode 100755 index 0feac57f0..000000000 --- a/tests/Cache/CacheMemcachedConnectorTest.php +++ /dev/null @@ -1,40 +0,0 @@ -getMock(MemcachedConnector::class, ['getMemcached']); - $memcached = m::mock('stdClass'); - $memcached->shouldReceive('addServer')->once()->with('localhost', 11211, 100); - $memcached->shouldReceive('getVersion')->once()->andReturn(true); - $connector->expects($this->once())->method('getMemcached')->willReturn($memcached); - $result = $connector->connect([['host' => 'localhost', 'port' => 11211, 'weight' => 100]]); - - $this->assertSame($result, $memcached); - } - - - public function testExceptionThrownOnBadConnection() - { - $this->expectException(RuntimeException::class); - $connector = $this->getMock(MemcachedConnector::class, ['getMemcached']); - $memcached = m::mock('stdClass'); - $memcached->shouldReceive('addServer')->once()->with('localhost', 11211, 100); - $memcached->shouldReceive('getVersion')->once()->andReturn(false); - $connector->expects($this->once())->method('getMemcached')->willReturn($memcached); - $result = $connector->connect([['host' => 'localhost', 'port' => 11211, 'weight' => 100]]); - } - -} diff --git a/tests/Cache/CacheMemcachedStoreTest.php b/tests/Cache/CacheMemcachedStoreTest.php deleted file mode 100755 index edb793a2c..000000000 --- a/tests/Cache/CacheMemcachedStoreTest.php +++ /dev/null @@ -1,76 +0,0 @@ -markTestSkipped("We dont use Memcached"); - } - - public function testGetReturnsNullWhenNotFound() - { - $memcache = $this->getMock(stdClass::class, ['get', 'getResultCode']); - $memcache->expects($this->once())->method('get')->with($this->equalTo('foo:bar'))->willReturn(null); - $memcache->expects($this->once())->method('getResultCode')->willReturn(1); - $store = new Illuminate\Cache\MemcachedStore($memcache, 'foo'); - $this->assertNull($store->get('bar')); - } - - - public function testMemcacheValueIsReturned() - { - $memcache = $this->getMock(stdClass::class, ['get', 'getResultCode']); - $memcache->expects($this->once())->method('get')->willReturn('bar'); - $memcache->expects($this->once())->method('getResultCode')->willReturn(0); - $store = new Illuminate\Cache\MemcachedStore($memcache); - $this->assertEquals('bar', $store->get('foo')); - } - - - public function testSetMethodProperlyCallsMemcache() - { - $memcache = $this->getMock(Memcached::class, ['set']); - $memcache->expects($this->once())->method('set')->with($this->equalTo('foo'), $this->equalTo('bar'), $this->equalTo(60)); - $store = new Illuminate\Cache\MemcachedStore($memcache); - $store->put('foo', 'bar', 1); - } - - - public function testIncrementMethodProperlyCallsMemcache() - { - $memcache = $this->getMock(Memcached::class, ['increment']); - $memcache->expects($this->once())->method('increment')->with($this->equalTo('foo'), $this->equalTo(5)); - $store = new Illuminate\Cache\MemcachedStore($memcache); - $store->increment('foo', 5); - } - - - public function testDecrementMethodProperlyCallsMemcache() - { - $memcache = $this->getMock(Memcached::class, ['decrement']); - $memcache->expects($this->once())->method('decrement')->with($this->equalTo('foo'), $this->equalTo(5)); - $store = new Illuminate\Cache\MemcachedStore($memcache); - $store->decrement('foo', 5); - } - - - public function testStoreItemForeverProperlyCallsMemcached() - { - $memcache = $this->getMock(Memcached::class, ['set']); - $memcache->expects($this->once())->method('set')->with($this->equalTo('foo'), $this->equalTo('bar'), $this->equalTo(0)); - $store = new Illuminate\Cache\MemcachedStore($memcache); - $store->forever('foo', 'bar'); - } - - - public function testForgetMethodProperlyCallsMemcache() - { - $memcache = $this->getMock(Memcached::class, ['delete']); - $memcache->expects($this->once())->method('delete')->with($this->equalTo('foo')); - $store = new Illuminate\Cache\MemcachedStore($memcache); - $store->forget('foo'); - } - -} diff --git a/tests/Cache/CacheNullStoreTest.php b/tests/Cache/CacheNullStoreTest.php deleted file mode 100644 index f0f09cb4a..000000000 --- a/tests/Cache/CacheNullStoreTest.php +++ /dev/null @@ -1,15 +0,0 @@ -put('foo', 'bar', 10); - $this->assertNull($store->get('foo')); - } - -} diff --git a/tests/Cache/CacheRedisStoreTest.php b/tests/Cache/CacheRedisStoreTest.php deleted file mode 100755 index 851f5702f..000000000 --- a/tests/Cache/CacheRedisStoreTest.php +++ /dev/null @@ -1,102 +0,0 @@ -getRedis(); - $redis->getRedis()->shouldReceive('connection')->once()->with('default')->andReturn($redis->getRedis()); - $redis->getRedis()->shouldReceive('get')->once()->with('prefix:foo')->andReturn(null); - $this->assertNull($redis->get('foo')); - } - - - public function testRedisValueIsReturned() - { - $redis = $this->getRedis(); - $redis->getRedis()->shouldReceive('connection')->once()->with('default')->andReturn($redis->getRedis()); - $redis->getRedis()->shouldReceive('get')->once()->with('prefix:foo')->andReturn(serialize('foo')); - $this->assertEquals('foo', $redis->get('foo')); - } - - - public function testRedisValueIsReturnedForNumerics() - { - $redis = $this->getRedis(); - $redis->getRedis()->shouldReceive('connection')->once()->with('default')->andReturn($redis->getRedis()); - $redis->getRedis()->shouldReceive('get')->once()->with('prefix:foo')->andReturn(1); - $this->assertEquals(1, $redis->get('foo')); - } - - - public function testSetMethodProperlyCallsRedis() - { - $redis = $this->getRedis(); - $redis->getRedis()->shouldReceive('connection')->once()->with('default')->andReturn($redis->getRedis()); - $redis->getRedis()->shouldReceive('setex')->once()->with('prefix:foo', 60 * 60, serialize('foo')); - $redis->put('foo', 'foo', 60); - } - - - public function testSetMethodProperlyCallsRedisForNumerics() - { - $redis = $this->getRedis(); - $redis->getRedis()->shouldReceive('connection')->once()->with('default')->andReturn($redis->getRedis()); - $redis->getRedis()->shouldReceive('setex')->once()->with('prefix:foo', 60 * 60, 1); - $redis->put('foo', 1, 60); - } - - - public function testIncrementMethodProperlyCallsRedis() - { - $redis = $this->getRedis(); - $redis->getRedis()->shouldReceive('connection')->once()->with('default')->andReturn($redis->getRedis()); - $redis->getRedis()->shouldReceive('incrby')->once()->with('prefix:foo', 5); - $redis->increment('foo', 5); - } - - - public function testDecrementMethodProperlyCallsRedis() - { - $redis = $this->getRedis(); - $redis->getRedis()->shouldReceive('connection')->once()->with('default')->andReturn($redis->getRedis()); - $redis->getRedis()->shouldReceive('decrby')->once()->with('prefix:foo', 5); - $redis->decrement('foo', 5); - } - - - public function testStoreItemForeverProperlyCallsRedis() - { - $redis = $this->getRedis(); - $redis->getRedis()->shouldReceive('connection')->once()->with('default')->andReturn($redis->getRedis()); - $redis->getRedis()->shouldReceive('set')->once()->with('prefix:foo', serialize('foo')); - $redis->forever('foo', 'foo', 60); - } - - - public function testForgetMethodProperlyCallsRedis() - { - $redis = $this->getRedis(); - $redis->getRedis()->shouldReceive('connection')->once()->with('default')->andReturn($redis->getRedis()); - $redis->getRedis()->shouldReceive('del')->once()->with('prefix:foo'); - $redis->forget('foo'); - } - - - protected function getRedis() - { - return new Illuminate\Cache\RedisStore(m::mock(Database::class), 'prefix'); - } - -} diff --git a/tests/Cache/CacheRepositoryTest.php b/tests/Cache/CacheRepositoryTest.php deleted file mode 100755 index 67453db75..000000000 --- a/tests/Cache/CacheRepositoryTest.php +++ /dev/null @@ -1,94 +0,0 @@ -getRepository(); - $repo->getStore()->shouldReceive('get')->once()->with('foo')->andReturn('bar'); - $this->assertEquals('bar', $repo->get('foo')); - } - - - public function testDefaultValueIsReturned() - { - $repo = $this->getRepository(); - $repo->getStore()->shouldReceive('get')->andReturn(null); - $this->assertEquals('bar', $repo->get('foo', 'bar')); - $this->assertEquals('baz', $repo->get('boom', function() { return 'baz'; })); - } - - - public function testSettingDefaultCacheTime() - { - $repo = $this->getRepository(); - $repo->setDefaultCacheTime(10); - $this->assertEquals(10, $repo->getDefaultCacheTime()); - } - - - public function testHasMethod() - { - $repo = $this->getRepository(); - $repo->getStore()->shouldReceive('get')->once()->with('foo')->andReturn(null); - $repo->getStore()->shouldReceive('get')->once()->with('bar')->andReturn('bar'); - - $this->assertTrue($repo->has('bar')); - $this->assertFalse($repo->has('foo')); - } - - - public function testRememberMethodCallsPutAndReturnsDefault() - { - $repo = $this->getRepository(); - $repo->getStore()->shouldReceive('get')->andReturn(null); - $repo->getStore()->shouldReceive('put')->once()->with('foo', 'bar', m::type('int')); - $result = $repo->remember('foo', Carbon::now()->addMinutes(10), function() { return 'bar'; }); - $this->assertEquals('bar', $result); - } - - - public function testPutAcceptsDateIntervalTtl() - { - $repo = $this->getRepository(); - $repo->getStore()->shouldReceive('put')->once()->with('foo', 'bar', m::type('int')); - $repo->put('foo', 'bar', new DateInterval('PT10M')); - } - - - public function testRememberForeverMethodCallsForeverAndReturnsDefault() - { - $repo = $this->getRepository(); - $repo->getStore()->shouldReceive('get')->andReturn(null); - $repo->getStore()->shouldReceive('forever')->once()->with('foo', 'bar'); - $result = $repo->rememberForever('foo', function() { return 'bar'; }); - $this->assertEquals('bar', $result); - } - - - public function testRegisterMacroWithNonStaticCall() - { - $repo = $this->getRepository(); - $repo::macro(__CLASS__, function() { return 'Taylor'; }); - $this->assertEquals($repo->{__CLASS__}(), 'Taylor'); - } - - - protected function getRepository() - { - return new Illuminate\Cache\Repository(m::mock(StoreInterface::class)); - } - -} diff --git a/tests/Cache/CacheTaggedCacheTest.php b/tests/Cache/CacheTaggedCacheTest.php deleted file mode 100644 index f1fb4199a..000000000 --- a/tests/Cache/CacheTaggedCacheTest.php +++ /dev/null @@ -1,115 +0,0 @@ -section('bop')->put('foo', 'bar', Carbon::now()->addMinutes(10)); - $store->section('zap')->put('baz', 'boom', Carbon::now()->addMinutes(10)); - $store->section('bop')->flush(); - $this->assertNull($store->section('bop')->get('foo')); - $this->assertEquals('boom', $store->section('zap')->get('baz')); - } - - - public function testCacheCanBeSavedWithMultipleTags() - { - $store = new ArrayStore; - $tags = ['bop', 'zap']; - $store->tags($tags)->put('foo', 'bar', Carbon::now()->addMinutes(10)); - $this->assertEquals('bar', $store->tags($tags)->get('foo')); - } - - - public function testCacheCanBeSetWithDatetimeArgument() - { - $store = new ArrayStore; - $tags = ['bop', 'zap']; - $duration = new DateTime(); - $duration->add(new DateInterval("PT10M")); - $store->tags($tags)->put('foo', 'bar', $duration); - $this->assertEquals('bar', $store->tags($tags)->get('foo')); - } - - - public function testCacheSavedWithMultipleTagsCanBeFlushed() - { - $store = new ArrayStore; - $tags1 = ['bop', 'zap']; - $store->tags($tags1)->put('foo', 'bar', Carbon::now()->addMinutes(10)); - $tags2 = ['bam', 'pow']; - $store->tags($tags2)->put('foo', 'bar', Carbon::now()->addMinutes(10)); - $store->tags('zap')->flush(); - $this->assertNull($store->tags($tags1)->get('foo')); - $this->assertEquals('bar', $store->tags($tags2)->get('foo')); - } - - - public function testTagsWithStringArgument() - { - $store = new ArrayStore; - $store->tags('bop')->put('foo', 'bar', Carbon::now()->addMinutes(10)); - $this->assertEquals('bar', $store->tags('bop')->get('foo')); - } - - - public function testTagsCacheForever() - { - $store = new ArrayStore; - $tags = ['bop', 'zap']; - $store->tags($tags)->forever('foo', 'bar'); - $this->assertEquals('bar', $store->tags($tags)->get('foo')); - } - - - public function testRedisCacheTagsPushForeverKeysCorrectly() - { - $store = m::mock(StoreInterface::class); - $tagSet = m::mock(TagSet::class, [$store, ['foo', 'bar']]); - $tagSet->shouldReceive('getNamespace')->andReturn('foo|bar'); - $redis = new Illuminate\Cache\RedisTaggedCache($store, $tagSet); - $store->shouldReceive('getPrefix')->andReturn('prefix:'); - $store->shouldReceive('connection')->andReturn($conn = m::mock('StdClass')); - $conn->shouldReceive('lpush')->once()->with('prefix:foo:forever', 'prefix:'.sha1('foo|bar').':key1'); - $conn->shouldReceive('lpush')->once()->with('prefix:bar:forever', 'prefix:'.sha1('foo|bar').':key1'); - $store->shouldReceive('forever')->with(sha1('foo|bar').':key1', 'key1:value'); - - $redis->forever('key1', 'key1:value'); - } - - - public function testRedisCacheForeverTagsCanBeFlushed() - { - $store = m::mock(StoreInterface::class); - $tagSet = m::mock(TagSet::class, [$store, ['foo', 'bar']]); - $tagSet->shouldReceive('getNamespace')->andReturn('foo|bar'); - $redis = new Illuminate\Cache\RedisTaggedCache($store, $tagSet); - $store->shouldReceive('getPrefix')->andReturn('prefix:'); - $store->shouldReceive('connection')->andReturn($conn = m::mock('StdClass')); - $conn->shouldReceive('lrange')->once()->with('prefix:foo:forever', 0, -1)->andReturn(['key1', 'key2']); - $conn->shouldReceive('lrange')->once()->with('prefix:bar:forever', 0, -1)->andReturn(['key3']); - $conn->shouldReceive('del')->once()->with('key1', 'key2'); - $conn->shouldReceive('del')->once()->with('key3'); - $conn->shouldReceive('del')->once()->with('prefix:foo:forever'); - $conn->shouldReceive('del')->once()->with('prefix:bar:forever'); - $tagSet->shouldReceive('reset')->once(); - - $redis->flush(); - } - -} diff --git a/tests/CachedRouting/RoutingIntegrationTest.php b/tests/CachedRouting/RoutingIntegrationTest.php index c27b700d6..7776713f7 100755 --- a/tests/CachedRouting/RoutingIntegrationTest.php +++ b/tests/CachedRouting/RoutingIntegrationTest.php @@ -95,8 +95,9 @@ protected function refreshApplication(): void $this->app['files'] = new Filesystem; $this->app['cache'] = new CacheManager($this->app); - $this->app['config']['cache.driver'] = 'file'; - $this->app['config']['cache.path'] = self::$cachePath = sys_get_temp_dir() . '/l42x-route-cache-' . uniqid(); + self::$cachePath = sys_get_temp_dir() . '/l42x-route-cache-' . uniqid(); + $this->app['config']['cache.default'] = 'file'; + $this->app['config']['cache.stores.file'] = ['driver' => 'file', 'path' => self::$cachePath]; $this->app['session'] = new SessionManager($this->app); $this->app['config']['session.driver'] = 'array'; diff --git a/tests/Console/ConsoleApplicationTest.php b/tests/Console/ConsoleApplicationTest.php deleted file mode 100755 index 6a5813adb..000000000 --- a/tests/Console/ConsoleApplicationTest.php +++ /dev/null @@ -1,100 +0,0 @@ -getMock(\Illuminate\Console\Application::class, ['addToParent']); - $app->setLaravel('foo'); - $command = m::mock(\Illuminate\Console\Command::class); - $command->shouldReceive('setLaravel')->once()->with('foo'); - $app->expects($this->once())->method('addToParent')->with($this->equalTo($command))->willReturn($command); - $result = $app->add($command); - - $this->assertEquals($command, $result); - } - - - public function testLaravelNotSetOnSymfonyCommands() - { - $app = $this->getMock(\Illuminate\Console\Application::class, ['addToParent']); - $app->setLaravel('foo'); - $command = m::mock(Command::class); - $command->shouldReceive('setLaravel')->never(); - $app->expects($this->once())->method('addToParent')->with($this->equalTo($command))->willReturn($command); - $result = $app->add($command); - - $this->assertEquals($command, $result); - } - - - public function testResolveAddsCommandViaApplicationResolution() - { - $app = $this->getMock(\Illuminate\Console\Application::class, ['addToParent']); - $command = m::mock(Command::class); - $app->setLaravel(['foo' => $command]); - $app->expects($this->once())->method('addToParent')->with($this->equalTo($command))->willReturn($command); - $result = $app->resolve('foo'); - - $this->assertEquals($command, $result); - } - - - public function testResolveCommandsCallsResolveForAllCommandsItsGiven() - { - $app = m::mock('Illuminate\Console\Application[resolve]'); - $app->shouldReceive('resolve')->twice()->with('foo'); - $app->resolveCommands('foo', 'foo'); - } - - - public function testResolveCommandsCallsResolveForAllCommandsItsGivenViaArray() - { - $app = m::mock('Illuminate\Console\Application[resolve]'); - $app->shouldReceive('resolve')->twice()->with('foo'); - $app->resolveCommands(['foo', 'foo']); - } - - - public function testExecuteResolvesHandleThenFallsBackToFire() - { - $execute = new \ReflectionMethod(\Illuminate\Console\Command::class, 'execute'); - $execute->setAccessible(true); - $input = new ArrayInput([]); - $output = new NullOutput; - - // handle() is preferred (L13 idiom) - $this->assertSame(0, $execute->invoke(new ConsoleHandleStub, $input, $output)); - $this->assertEquals('handle', $_SERVER['__console.ran']); - - // fire() still runs as the L4.2 fallback when no handle() exists - $execute->invoke(new ConsoleFireStub, $input, $output); - $this->assertEquals('fire', $_SERVER['__console.ran']); - } - -} - -class ConsoleHandleStub extends \Illuminate\Console\Command -{ - protected $name = 'stub:handle'; - public function handle() { $_SERVER['__console.ran'] = 'handle'; } -} - -class ConsoleFireStub extends \Illuminate\Console\Command -{ - protected $name = 'stub:fire'; - public function fire() { $_SERVER['__console.ran'] = 'fire'; } -} diff --git a/tests/Container/ContainerCallTest.php b/tests/Container/ContainerCallTest.php deleted file mode 100644 index 41fe88f3d..000000000 --- a/tests/Container/ContainerCallTest.php +++ /dev/null @@ -1,295 +0,0 @@ -expectException(Error::class); - $this->expectExceptionMessage('Call to undefined function ContainerTestCallStub()'); - - $container = new Container; - $container->call('ContainerTestCallStub'); - } - - public function testCallWithAtSignBasedClassReferences(): void - { - $container = new Container; - $result = $container->call(ContainerTestCallStub::class.'@work', ['foo', 'bar']); - $this->assertEquals(['foo', 'bar'], $result); - - $container = new Container; - $result = $container->call(ContainerTestCallStub::class.'@inject'); - $this->assertInstanceOf(ContainerCallConcreteStub::class, $result[0]); - $this->assertSame('taylor', $result[1]); - - $container = new Container; - $result = $container->call(ContainerTestCallStub::class.'@inject', ['default' => 'foo']); - $this->assertInstanceOf(ContainerCallConcreteStub::class, $result[0]); - $this->assertSame('foo', $result[1]); - - $container = new Container; - $result = $container->call(ContainerTestCallStub::class, ['foo', 'bar'], 'work'); - $this->assertEquals(['foo', 'bar'], $result); - } - - public function testCallWithCallableArray(): void - { - $container = new Container; - $stub = new ContainerTestCallStub; - $result = $container->call([$stub, 'work'], ['foo', 'bar']); - $this->assertEquals(['foo', 'bar'], $result); - } - - public function testCallWithStaticMethodNameString(): void - { - $container = new Container; - $result = $container->call('Illuminate\Tests\Container\ContainerStaticMethodStub::inject'); - $this->assertInstanceOf(ContainerCallConcreteStub::class, $result[0]); - $this->assertSame('taylor', $result[1]); - } - - public function testCallWithGlobalMethodName(): void - { - $container = new Container; - $result = $container->call('Illuminate\Tests\Container\containerTestInject'); - $this->assertInstanceOf(ContainerCallConcreteStub::class, $result[0]); - $this->assertSame('taylor', $result[1]); - } - - public function testCallWithBoundMethod(): void - { - $container = new Container; - $container->bindMethod(ContainerTestCallStub::class.'@unresolvable', function ($stub) { - return $stub->unresolvable('foo', 'bar'); - }); - $result = $container->call(ContainerTestCallStub::class.'@unresolvable'); - $this->assertEquals(['foo', 'bar'], $result); - - $container = new Container; - $container->bindMethod(ContainerTestCallStub::class.'@unresolvable', function ($stub) { - return $stub->unresolvable('foo', 'bar'); - }); - $result = $container->call([new ContainerTestCallStub, 'unresolvable']); - $this->assertEquals(['foo', 'bar'], $result); - - $container = new Container; - $result = $container->call([new ContainerTestCallStub, 'inject'], ['_stub' => 'foo', 'default' => 'bar']); - $this->assertInstanceOf(ContainerCallConcreteStub::class, $result[0]); - $this->assertSame('bar', $result[1]); - - $container = new Container; - $result = $container->call([new ContainerTestCallStub, 'inject'], ['_stub' => 'foo']); - $this->assertInstanceOf(ContainerCallConcreteStub::class, $result[0]); - $this->assertSame('taylor', $result[1]); - } - - public function testBindMethodAcceptsAnArray(): void - { - $container = new Container; - $container->bindMethod([ContainerTestCallStub::class, 'unresolvable'], function ($stub) { - return $stub->unresolvable('foo', 'bar'); - }); - $result = $container->call(ContainerTestCallStub::class.'@unresolvable'); - $this->assertEquals(['foo', 'bar'], $result); - - $container = new Container; - $container->bindMethod([ContainerTestCallStub::class, 'unresolvable'], function ($stub) { - return $stub->unresolvable('foo', 'bar'); - }); - $result = $container->call([new ContainerTestCallStub, 'unresolvable']); - $this->assertEquals(['foo', 'bar'], $result); - } - - public function testClosureCallWithInjectedDependency(): void - { - $container = new Container; - $container->call(function (ContainerCallConcreteStub $stub) { - // - }, ['foo' => 'bar']); - - $container->call(function (ContainerCallConcreteStub $stub) { - // - }, ['foo' => 'bar', 'stub' => new ContainerCallConcreteStub]); - } - - public function testCallWithDependencies(): void - { - $container = new Container; - $result = $container->call(function (stdClass $foo, $bar = []) { - return func_get_args(); - }); - - $this->assertInstanceOf(stdClass::class, $result[0]); - $this->assertEquals([], $result[1]); - - $result = $container->call(function (stdClass $foo, $bar = []) { - return func_get_args(); - }, ['bar' => 'taylor']); - - $this->assertInstanceOf(stdClass::class, $result[0]); - $this->assertSame('taylor', $result[1]); - - $stub = new ContainerCallConcreteStub; - $result = $container->call(function (stdClass $foo, ContainerCallConcreteStub $bar) { - return func_get_args(); - }, [ContainerCallConcreteStub::class => $stub]); - - $this->assertInstanceOf(stdClass::class, $result[0]); - $this->assertSame($stub, $result[1]); - - /* - * Wrap a function... - */ - $result = $container->wrap(function (stdClass $foo, $bar = []) { - return func_get_args(); - }, ['bar' => 'taylor']); - - $this->assertInstanceOf(Closure::class, $result); - $result = $result(); - - $this->assertInstanceOf(stdClass::class, $result[0]); - $this->assertSame('taylor', $result[1]); - } - - public function testCallWithVariadicDependency(): void - { - $stub1 = new ContainerCallConcreteStub; - $stub2 = new ContainerCallConcreteStub; - - $container = new Container; - $container->bind(ContainerCallConcreteStub::class, function () use ($stub1, $stub2) { - return [ - $stub1, - $stub2, - ]; - }); - - $result = $container->call(function (stdClass $foo, ContainerCallConcreteStub ...$bar) { - return func_get_args(); - }); - - $this->assertInstanceOf(stdClass::class, $result[0]); - $this->assertInstanceOf(ContainerCallConcreteStub::class, $result[1]); - $this->assertSame($stub1, $result[1]); - $this->assertSame($stub2, $result[2]); - } - - public function testCallWithCallableObject(): void - { - $container = new Container; - $callable = new ContainerCallCallableStub; - $result = $container->call($callable); - $this->assertInstanceOf(ContainerCallConcreteStub::class, $result[0]); - $this->assertSame('jeffrey', $result[1]); - } - - public function testCallWithCallableClassString(): void - { - $container = new Container; - $result = $container->call(ContainerCallCallableClassStringStub::class); - $this->assertInstanceOf(ContainerCallConcreteStub::class, $result[0]); - $this->assertSame('jeffrey', $result[1]); - $this->assertInstanceOf(ContainerTestCallStub::class, $result[2]); - } - - public function testCallWithoutRequiredParamsThrowsException(): void - { - $this->expectException(BindingResolutionException::class); - $this->expectExceptionMessage('Unable to resolve dependency [Parameter #0 [ $foo ]] in class Illuminate\Tests\Container\ContainerTestCallStub'); - - $container = new Container; - $container->call(ContainerTestCallStub::class.'@unresolvable'); - } - - public function testCallWithUnnamedParametersThrowsException(): void - { - $this->expectException(BindingResolutionException::class); - $this->expectExceptionMessage('Unable to resolve dependency [Parameter #0 [ $foo ]] in class Illuminate\Tests\Container\ContainerTestCallStub'); - - $container = new Container; - $container->call([new ContainerTestCallStub, 'unresolvable'], ['foo', 'bar']); - } - - public function testCallWithoutRequiredParamsOnClosureThrowsException(): void - { - $this->expectException(BindingResolutionException::class); - $this->expectExceptionMessage('Unable to resolve dependency [Parameter #0 [ $foo ]] in class Illuminate\Tests\Container\ContainerCallTest'); - - $container = new Container; - $container->call(function ($foo, $bar = 'default') { - return $foo; - }); - } -} - -class ContainerTestCallStub -{ - public function work(): array - { - return func_get_args(); - } - - public function inject(ContainerCallConcreteStub $stub, $default = 'taylor'): array - { - return func_get_args(); - } - - public function unresolvable($foo, $bar): array - { - return func_get_args(); - } -} - -class ContainerCallConcreteStub -{ - // -} - -function containerTestInject(ContainerCallConcreteStub $stub, $default = 'taylor') -{ - return func_get_args(); -} - -class ContainerStaticMethodStub -{ - public static function inject(ContainerCallConcreteStub $stub, $default = 'taylor'): array - { - return func_get_args(); - } -} - -class ContainerCallCallableStub -{ - public function __invoke(ContainerCallConcreteStub $stub, $default = 'jeffrey') - { - return func_get_args(); - } -} - -class ContainerCallCallableClassStringStub -{ - public $stub; - - public $default; - - public function __construct(ContainerCallConcreteStub $stub, $default = 'jeffrey') - { - $this->stub = $stub; - $this->default = $default; - } - - public function __invoke(ContainerTestCallStub $dependency) - { - return [$this->stub, $this->default, $dependency]; - } -} \ No newline at end of file diff --git a/tests/Container/ContainerContextualBindingTest.php b/tests/Container/ContainerContextualBindingTest.php deleted file mode 100644 index bba576471..000000000 --- a/tests/Container/ContainerContextualBindingTest.php +++ /dev/null @@ -1,635 +0,0 @@ -bind(IContainerContextContractStub::class, ContainerContextImplementationStub::class); - - $container->when(ContainerTestContextInjectOne::class)->needs(IContainerContextContractStub::class)->give(ContainerContextImplementationStub::class); - $container->when(ContainerTestContextInjectTwo::class)->needs(IContainerContextContractStub::class)->give(ContainerContextImplementationStubTwo::class); - - $one = $container->make(ContainerTestContextInjectOne::class); - $two = $container->make(ContainerTestContextInjectTwo::class); - - $this->assertInstanceOf(ContainerContextImplementationStub::class, $one->impl); - $this->assertInstanceOf(ContainerContextImplementationStubTwo::class, $two->impl); - - /* - * Test With Closures - */ - $container = new Container; - - $container->bind(IContainerContextContractStub::class, ContainerContextImplementationStub::class); - - $container->when(ContainerTestContextInjectOne::class)->needs(IContainerContextContractStub::class)->give(ContainerContextImplementationStub::class); - $container->when(ContainerTestContextInjectTwo::class)->needs(IContainerContextContractStub::class)->give(function ($container) { - return $container->make(ContainerContextImplementationStubTwo::class); - }); - - $one = $container->make(ContainerTestContextInjectOne::class); - $two = $container->make(ContainerTestContextInjectTwo::class); - - $this->assertInstanceOf(ContainerContextImplementationStub::class, $one->impl); - $this->assertInstanceOf(ContainerContextImplementationStubTwo::class, $two->impl); - } - - public function testContextualBindingWorksForExistingInstancedBindings(): void - { - $container = new Container; - - $container->instance(IContainerContextContractStub::class, new ContainerContextImplementationStub); - - $container->when(ContainerTestContextInjectOne::class)->needs(IContainerContextContractStub::class)->give(ContainerContextImplementationStubTwo::class); - - $this->assertInstanceOf(ContainerContextImplementationStubTwo::class, $container->make(ContainerTestContextInjectOne::class)->impl); - } - - public function testContextualBindingWorksForNewlyInstancedBindings(): void - { - $container = new Container; - - $container->when(ContainerTestContextInjectOne::class)->needs(IContainerContextContractStub::class)->give(ContainerContextImplementationStubTwo::class); - - $container->instance(IContainerContextContractStub::class, new ContainerContextImplementationStub); - - $this->assertInstanceOf( - ContainerContextImplementationStubTwo::class, - $container->make(ContainerTestContextInjectOne::class)->impl - ); - } - - public function testContextualBindingWorksOnExistingAliasedInstances(): void - { - $container = new Container; - - $container->instance('stub', new ContainerContextImplementationStub); - $container->alias('stub', IContainerContextContractStub::class); - - $container->when(ContainerTestContextInjectOne::class)->needs(IContainerContextContractStub::class)->give(ContainerContextImplementationStubTwo::class); - - $this->assertInstanceOf( - ContainerContextImplementationStubTwo::class, - $container->make(ContainerTestContextInjectOne::class)->impl - ); - } - - public function testContextualBindingWorksOnNewAliasedInstances(): void - { - $container = new Container; - - $container->when(ContainerTestContextInjectOne::class)->needs(IContainerContextContractStub::class)->give(ContainerContextImplementationStubTwo::class); - - $container->instance('stub', new ContainerContextImplementationStub); - $container->alias('stub', IContainerContextContractStub::class); - - $this->assertInstanceOf( - ContainerContextImplementationStubTwo::class, - $container->make(ContainerTestContextInjectOne::class)->impl - ); - } - - public function testContextualBindingWorksOnNewAliasedBindings(): void - { - $container = new Container; - - $container->when(ContainerTestContextInjectOne::class)->needs(IContainerContextContractStub::class)->give(ContainerContextImplementationStubTwo::class); - - $container->bind('stub', ContainerContextImplementationStub::class); - $container->alias('stub', IContainerContextContractStub::class); - - $this->assertInstanceOf( - ContainerContextImplementationStubTwo::class, - $container->make(ContainerTestContextInjectOne::class)->impl - ); - } - - public function testContextualBindingWorksForMultipleClasses(): void - { - $container = new Container; - - $container->bind(IContainerContextContractStub::class, ContainerContextImplementationStub::class); - - $container->when([ContainerTestContextInjectTwo::class, ContainerTestContextInjectThree::class])->needs(IContainerContextContractStub::class)->give(ContainerContextImplementationStubTwo::class); - - $this->assertInstanceOf( - ContainerContextImplementationStub::class, - $container->make(ContainerTestContextInjectOne::class)->impl - ); - - $this->assertInstanceOf( - ContainerContextImplementationStubTwo::class, - $container->make(ContainerTestContextInjectTwo::class)->impl - ); - - $this->assertInstanceOf( - ContainerContextImplementationStubTwo::class, - $container->make(ContainerTestContextInjectThree::class)->impl - ); - } - - public function testContextualBindingDoesntOverrideNonContextualResolution(): void - { - $container = new Container; - - $container->instance('stub', new ContainerContextImplementationStub); - $container->alias('stub', IContainerContextContractStub::class); - - $container->when(ContainerTestContextInjectTwo::class)->needs(IContainerContextContractStub::class)->give(ContainerContextImplementationStubTwo::class); - - $this->assertInstanceOf( - ContainerContextImplementationStubTwo::class, - $container->make(ContainerTestContextInjectTwo::class)->impl - ); - - $this->assertInstanceOf( - ContainerContextImplementationStub::class, - $container->make(ContainerTestContextInjectOne::class)->impl - ); - } - - public function testContextuallyBoundInstancesAreNotUnnecessarilyRecreated(): void - { - ContainerTestContextInjectInstantiations::$instantiations = 0; - - $container = new Container; - - $container->instance(IContainerContextContractStub::class, new ContainerContextImplementationStub); - $container->instance(ContainerTestContextInjectInstantiations::class, new ContainerTestContextInjectInstantiations); - - $this->assertEquals(1, ContainerTestContextInjectInstantiations::$instantiations); - - $container->when(ContainerTestContextInjectOne::class)->needs(IContainerContextContractStub::class)->give(ContainerTestContextInjectInstantiations::class); - - $container->make(ContainerTestContextInjectOne::class); - $container->make(ContainerTestContextInjectOne::class); - $container->make(ContainerTestContextInjectOne::class); - $container->make(ContainerTestContextInjectOne::class); - - $this->assertEquals(1, ContainerTestContextInjectInstantiations::$instantiations); - } - - public function testContainerCanInjectSimpleVariable(): void - { - $container = new Container; - $container->when(ContainerInjectVariableStub::class)->needs('$something')->give(100); - $instance = $container->make(ContainerInjectVariableStub::class); - $this->assertEquals(100, $instance->something); - - $container = new Container; - $container->when(ContainerInjectVariableStub::class)->needs('$something')->give(function ($container) { - return $container->make(ContainerContextualConcreteStub::class); - }); - $instance = $container->make(ContainerInjectVariableStub::class); - $this->assertInstanceOf(ContainerContextualConcreteStub::class, $instance->something); - } - - public function testContextualBindingWorksWithAliasedTargets(): void - { - $container = new Container; - - $container->bind(IContainerContextContractStub::class, ContainerContextImplementationStub::class); - $container->alias(IContainerContextContractStub::class, 'interface-stub'); - - $container->alias(ContainerContextImplementationStub::class, 'stub-1'); - - $container->when(ContainerTestContextInjectOne::class)->needs('interface-stub')->give('stub-1'); - $container->when(ContainerTestContextInjectTwo::class)->needs('interface-stub')->give(ContainerContextImplementationStubTwo::class); - - $one = $container->make(ContainerTestContextInjectOne::class); - $two = $container->make(ContainerTestContextInjectTwo::class); - - $this->assertInstanceOf(ContainerContextImplementationStub::class, $one->impl); - $this->assertInstanceOf(ContainerContextImplementationStubTwo::class, $two->impl); - } - - public function testContextualBindingWorksForNestedOptionalDependencies(): void - { - $container = new Container; - - $container->when(ContainerTestContextInjectTwoInstances::class)->needs(ContainerTestContextInjectTwo::class)->give(function () { - return new ContainerTestContextInjectTwo(new ContainerContextImplementationStubTwo); - }); - - $resolvedInstance = $container->make(ContainerTestContextInjectTwoInstances::class); - $this->assertInstanceOf( - ContainerTestContextWithOptionalInnerDependency::class, - $resolvedInstance->implOne - ); - $this->assertNull($resolvedInstance->implOne->inner); - - $this->assertInstanceOf( - ContainerTestContextInjectTwo::class, - $resolvedInstance->implTwo - ); - $this->assertInstanceOf(ContainerContextImplementationStubTwo::class, $resolvedInstance->implTwo->impl); - } - - public function testContextualBindingWorksForVariadicDependencies(): void - { - $container = new Container; - - $container->when(ContainerTestContextInjectVariadic::class)->needs(IContainerContextContractStub::class)->give(function ($c) { - return [ - $c->make(ContainerContextImplementationStub::class), - $c->make(ContainerContextImplementationStubTwo::class), - ]; - }); - - $resolvedInstance = $container->make(ContainerTestContextInjectVariadic::class); - - $this->assertCount(2, $resolvedInstance->stubs); - $this->assertInstanceOf(ContainerContextImplementationStub::class, $resolvedInstance->stubs[0]); - $this->assertInstanceOf(ContainerContextImplementationStubTwo::class, $resolvedInstance->stubs[1]); - } - - public function testContextualBindingWorksForVariadicDependenciesWithNothingBound(): void - { - $container = new Container; - - $resolvedInstance = $container->make(ContainerTestContextInjectVariadic::class); - - $this->assertCount(0, $resolvedInstance->stubs); - } - - public function testContextualBindingWorksForVariadicAfterNonVariadicDependencies(): void - { - $container = new Container; - - $container->when(ContainerTestContextInjectVariadicAfterNonVariadic::class)->needs(IContainerContextContractStub::class)->give(function ($c) { - return [ - $c->make(ContainerContextImplementationStub::class), - $c->make(ContainerContextImplementationStubTwo::class), - ]; - }); - - $resolvedInstance = $container->make(ContainerTestContextInjectVariadicAfterNonVariadic::class); - - $this->assertCount(2, $resolvedInstance->stubs); - $this->assertInstanceOf(ContainerContextImplementationStub::class, $resolvedInstance->stubs[0]); - $this->assertInstanceOf(ContainerContextImplementationStubTwo::class, $resolvedInstance->stubs[1]); - } - - public function testContextualBindingWorksForVariadicAfterNonVariadicDependenciesWithNothingBound(): void - { - $container = new Container; - - $resolvedInstance = $container->make(ContainerTestContextInjectVariadicAfterNonVariadic::class); - - $this->assertCount(0, $resolvedInstance->stubs); - } - - public function testContextualBindingWorksForVariadicDependenciesWithoutFactory(): void - { - $container = new Container; - - $container->when(ContainerTestContextInjectVariadic::class)->needs(IContainerContextContractStub::class)->give([ - ContainerContextImplementationStub::class, - ContainerContextImplementationStubTwo::class, - ]); - - $resolvedInstance = $container->make(ContainerTestContextInjectVariadic::class); - - $this->assertCount(2, $resolvedInstance->stubs); - $this->assertInstanceOf(ContainerContextImplementationStub::class, $resolvedInstance->stubs[0]); - $this->assertInstanceOf(ContainerContextImplementationStubTwo::class, $resolvedInstance->stubs[1]); - } - - public function testContextualBindingGivesTagsForArrayWithNoTagsDefined(): void - { - $container = new Container; - - $container->when(ContainerTestContextInjectArray::class)->needs('$stubs')->giveTagged('stub'); - - $resolvedInstance = $container->make(ContainerTestContextInjectArray::class); - - $this->assertCount(0, $resolvedInstance->stubs); - } - - public function testContextualBindingGivesTagsForVariadicWithNoTagsDefined(): void - { - $container = new Container; - - $container->when(ContainerTestContextInjectVariadic::class)->needs(IContainerContextContractStub::class)->giveTagged('stub'); - - $resolvedInstance = $container->make(ContainerTestContextInjectVariadic::class); - - $this->assertCount(0, $resolvedInstance->stubs); - } - - public function testContextualBindingGivesTagsForArray(): void - { - $container = new Container; - - $container->tag([ - ContainerContextImplementationStub::class, - ContainerContextImplementationStubTwo::class, - ], ['stub']); - - $container->when(ContainerTestContextInjectArray::class)->needs('$stubs')->giveTagged('stub'); - - $resolvedInstance = $container->make(ContainerTestContextInjectArray::class); - - $this->assertCount(2, $resolvedInstance->stubs); - $this->assertInstanceOf(ContainerContextImplementationStub::class, $resolvedInstance->stubs[0]); - $this->assertInstanceOf(ContainerContextImplementationStubTwo::class, $resolvedInstance->stubs[1]); - } - - public function testContextualBindingGivesTagsForVariadic(): void - { - $container = new Container; - - $container->tag([ - ContainerContextImplementationStub::class, - ContainerContextImplementationStubTwo::class, - ], ['stub']); - - $container->when(ContainerTestContextInjectVariadic::class)->needs(IContainerContextContractStub::class)->giveTagged('stub'); - - $resolvedInstance = $container->make(ContainerTestContextInjectVariadic::class); - - $this->assertCount(2, $resolvedInstance->stubs); - $this->assertInstanceOf(ContainerContextImplementationStub::class, $resolvedInstance->stubs[0]); - $this->assertInstanceOf(ContainerContextImplementationStubTwo::class, $resolvedInstance->stubs[1]); - } - - public function testContextualBindingGivesValuesFromConfigOptionalValueNull(): void - { - $config = $this->getConfigWithData('test', [ - 'username' => 'laravel', - 'password' => 'hunter42' - ]); - - $container = new Container; - $container->singleton('config', fn() => $config); - - $container - ->when(ContainerTestContextInjectFromConfigIndividualValues::class) - ->needs('$username') - ->giveConfig('test.username'); - - $container - ->when(ContainerTestContextInjectFromConfigIndividualValues::class) - ->needs('$password') - ->giveConfig('test.password'); - - $resolvedInstance = $container->make(ContainerTestContextInjectFromConfigIndividualValues::class); - - $this->assertSame('laravel', $resolvedInstance->username); - $this->assertSame('hunter42', $resolvedInstance->password); - $this->assertNull($resolvedInstance->alias); - } - - public function testContextualBindingGivesValuesFromConfigOptionalValueSet(): void - { - $config = $this->getConfigWithData('test', [ - 'username' => 'laravel', - 'password' => 'hunter42', - 'alias' => 'lumen' - ]); - - $container = new Container; - $container->singleton('config', fn() => $config); - - $container - ->when(ContainerTestContextInjectFromConfigIndividualValues::class) - ->needs('$username') - ->giveConfig('test.username'); - - $container - ->when(ContainerTestContextInjectFromConfigIndividualValues::class) - ->needs('$password') - ->giveConfig('test.password'); - - $container - ->when(ContainerTestContextInjectFromConfigIndividualValues::class) - ->needs('$alias') - ->giveConfig('test.alias'); - - $resolvedInstance = $container->make(ContainerTestContextInjectFromConfigIndividualValues::class); - - $this->assertSame('laravel', $resolvedInstance->username); - $this->assertSame('hunter42', $resolvedInstance->password); - $this->assertSame('lumen', $resolvedInstance->alias); - } - - public function testContextualBindingGivesValuesFromConfigWithDefault(): void - { - $config = $this->getConfigWithData('test', [ - 'password' => 'hunter42' - ]); - - $container = new Container; - $container->singleton('config', fn() => $config); - - $container - ->when(ContainerTestContextInjectFromConfigIndividualValues::class) - ->needs('$username') - ->giveConfig('test.username', 'DEFAULT_USERNAME'); - - $container - ->when(ContainerTestContextInjectFromConfigIndividualValues::class) - ->needs('$password') - ->giveConfig('test.password'); - - $resolvedInstance = $container->make(ContainerTestContextInjectFromConfigIndividualValues::class); - - $this->assertSame('DEFAULT_USERNAME', $resolvedInstance->username); - $this->assertSame('hunter42', $resolvedInstance->password); - $this->assertNull($resolvedInstance->alias); - } - - public function testContextualBindingGivesValuesFromConfigArray(): void - { - $config = $this->getConfigWithData('test', [ - 'username' => 'laravel', - 'password' => 'hunter42', - 'alias' => 'lumen' - ]); - - $container = new Container; - $container->singleton('config', fn() => $config); - - $container - ->when(ContainerTestContextInjectFromConfigArray::class) - ->needs('$settings') - ->giveConfig('test'); - - $resolvedInstance = $container->make(ContainerTestContextInjectFromConfigArray::class); - - $this->assertSame('laravel', $resolvedInstance->settings['username']); - $this->assertSame('hunter42', $resolvedInstance->settings['password']); - $this->assertSame('lumen', $resolvedInstance->settings['alias']); - } - - private function getConfigWithData(string $groupName, array $data = []): Repository { - $loader = $this->prophesize(\Illuminate\Config\LoaderInterface::class); - $loader->load(\Prophecy\Argument::any(), $groupName, \Prophecy\Argument::any())->willReturn($data); - return new Repository($loader->reveal(), 'production'); - } -} - -class ContainerContextualConcreteStub {} - -interface IContainerContextualContractStub {} - -class ContainerContextualImplementationStub implements IContainerContextualContractStub {} - -class ContainerInjectVariableStub -{ - public $something; - - public function __construct(ContainerContextualConcreteStub $concrete, $something) - { - $this->something = $something; - } -} - -interface IContainerContextContractStub -{ - // -} - -class ContainerContextNonContractStub -{ - // -} - -class ContainerContextImplementationStub implements IContainerContextContractStub -{ - // -} - -class ContainerContextImplementationStubTwo implements IContainerContextContractStub -{ - // -} - -class ContainerTestContextInjectInstantiations implements IContainerContextContractStub -{ - public static $instantiations; - - public function __construct() - { - static::$instantiations++; - } -} - -class ContainerTestContextInjectOne -{ - public $impl; - - public function __construct(IContainerContextContractStub $impl) - { - $this->impl = $impl; - } -} - -class ContainerTestContextInjectTwo -{ - public $impl; - - public function __construct(IContainerContextContractStub $impl) - { - $this->impl = $impl; - } -} - -class ContainerTestContextInjectThree -{ - public $impl; - - public function __construct(IContainerContextContractStub $impl) - { - $this->impl = $impl; - } -} - -class ContainerTestContextInjectTwoInstances -{ - public $implOne; - public $implTwo; - - public function __construct(ContainerTestContextWithOptionalInnerDependency $implOne, ContainerTestContextInjectTwo $implTwo) - { - $this->implOne = $implOne; - $this->implTwo = $implTwo; - } -} - -class ContainerTestContextWithOptionalInnerDependency -{ - public $inner; - - public function __construct(?ContainerTestContextInjectOne $inner = null) - { - $this->inner = $inner; - } -} - -class ContainerTestContextInjectArray -{ - public $stubs; - - public function __construct(array $stubs) - { - $this->stubs = $stubs; - } -} - -class ContainerTestContextInjectVariadic -{ - public array $stubs; - - public function __construct(IContainerContextContractStub ...$stubs) - { - $this->stubs = $stubs; - } -} - -class ContainerTestContextInjectVariadicAfterNonVariadic -{ - public $other; - public $stubs; - - public function __construct(ContainerContextNonContractStub $other, IContainerContextContractStub ...$stubs) - { - $this->other = $other; - $this->stubs = $stubs; - } -} - -class ContainerTestContextInjectFromConfigIndividualValues -{ - public $username; - public $password; - public $alias = null; - - public function __construct($username, $password, $alias = null) - { - $this->username = $username; - $this->password = $password; - $this->alias = $alias; - } -} - -class ContainerTestContextInjectFromConfigArray -{ - public $settings; - - public function __construct($settings) - { - $this->settings = $settings; - } -} \ No newline at end of file diff --git a/tests/Container/ContainerExtendTest.php b/tests/Container/ContainerExtendTest.php deleted file mode 100644 index f19659028..000000000 --- a/tests/Container/ContainerExtendTest.php +++ /dev/null @@ -1,200 +0,0 @@ -extend('foo', function ($old, $container) { - return $old.'bar'; - }); - - $this->assertSame('foobar', $container->make('foo')); - - $container = new Container; - - $container->singleton('foo', function () { - return (object) ['name' => 'taylor']; - }); - $container->extend('foo', function ($old, $container) { - $old->age = 26; - - return $old; - }); - - $result = $container->make('foo'); - - $this->assertSame('taylor', $result->name); - $this->assertEquals(26, $result->age); - $this->assertSame($result, $container->make('foo')); - } - - public function testExtendInstancesArePreserved(): void - { - $container = new Container; - $container->bind('foo', function () { - $obj = new stdClass; - $obj->foo = 'bar'; - - return $obj; - }); - - $obj = new stdClass; - $obj->foo = 'foo'; - $container->instance('foo', $obj); - $container->extend('foo', function ($obj, $container) { - $obj->bar = 'baz'; - - return $obj; - }); - $container->extend('foo', function ($obj, $container) { - $obj->baz = 'foo'; - - return $obj; - }); - - $this->assertSame('foo', $container->make('foo')->foo); - $this->assertSame('baz', $container->make('foo')->bar); - $this->assertSame('foo', $container->make('foo')->baz); - } - - public function testExtendIsLazyInitialized(): void - { - ContainerExtLazyExtendStub::$initialized = false; - - $container = new Container; - $container->bind(ContainerExtLazyExtendStub::class); - $container->extend(ContainerExtLazyExtendStub::class, function ($obj, $container) { - $obj->init(); - - return $obj; - }); - $this->assertFalse(ContainerExtLazyExtendStub::$initialized); - $container->make(ContainerExtLazyExtendStub::class); - $this->assertTrue(ContainerExtLazyExtendStub::$initialized); - } - - public function testExtendCanBeCalledBeforeBind(): void - { - $container = new Container; - $container->extend('foo', function ($old, $container) { - return $old.'bar'; - }); - $container['foo'] = 'foo'; - - $this->assertSame('foobar', $container->make('foo')); - } - - public function testExtendInstanceRebindingCallback(): void - { - $_SERVER['_test_rebind'] = false; - - $container = new Container; - $container->rebinding('foo', function () { - $_SERVER['_test_rebind'] = true; - }); - - $obj = new stdClass; - $container->instance('foo', $obj); - - $container->extend('foo', function ($obj, $container) { - return $obj; - }); - - $this->assertTrue($_SERVER['_test_rebind']); - } - - public function testExtendBindRebindingCallback(): void - { - $_SERVER['_test_rebind'] = false; - - $container = new Container; - $container->rebinding('foo', function () { - $_SERVER['_test_rebind'] = true; - }); - $container->bind('foo', function () { - return new stdClass; - }); - - $this->assertFalse($_SERVER['_test_rebind']); - - $container->make('foo'); - - $container->extend('foo', function ($obj, $container) { - return $obj; - }); - - $this->assertTrue($_SERVER['_test_rebind']); - } - - public function testExtensionWorksOnAliasedBindings(): void - { - $container = new Container; - $container->singleton('something', function () { - return 'some value'; - }); - $container->alias('something', 'something-alias'); - $container->extend('something-alias', function ($value) { - return $value.' extended'; - }); - - $this->assertSame('some value extended', $container->make('something')); - } - - public function testMultipleExtends(): void - { - $container = new Container; - $container['foo'] = 'foo'; - $container->extend('foo', function ($old, $container) { - return $old.'bar'; - }); - $container->extend('foo', function ($old, $container) { - return $old.'baz'; - }); - - $this->assertSame('foobarbaz', $container->make('foo')); - } - - public function testUnsetExtend(): void - { - $container = new Container; - $container->bind('foo', function () { - $obj = new stdClass; - $obj->foo = 'bar'; - - return $obj; - }); - - $container->extend('foo', function ($obj, $container) { - $obj->bar = 'baz'; - - return $obj; - }); - - unset($container['foo']); - $container->forgetExtenders('foo'); - - $container->bind('foo', function () { - return 'foo'; - }); - - $this->assertSame('foo', $container->make('foo')); - } -} - -class ContainerExtLazyExtendStub -{ - public static $initialized = false; - - public function init(): void - { - static::$initialized = true; - } -} \ No newline at end of file diff --git a/tests/Container/ContainerL4Test.php b/tests/Container/ContainerL4Test.php deleted file mode 100755 index 95ce3a3dc..000000000 --- a/tests/Container/ContainerL4Test.php +++ /dev/null @@ -1,366 +0,0 @@ -bind('name', function() { return 'Taylor'; }); - $this->assertEquals('Taylor', $container->make('name')); - } - - - public function testBindIfDoesntRegisterIfServiceAlreadyRegistered(): void - { - $container = new Container; - $container->bind('name', function() { return 'Taylor'; }); - $container->bindIf('name', function() { return 'Dayle'; }); - - $this->assertEquals('Taylor', $container->make('name')); - } - - - public function testSharedClosureResolution(): void - { - $container = new Container; - $class = new stdClass; - $container->singleton('class', function() use ($class) { return $class; }); - $this->assertSame($class, $container->make('class')); - } - - - public function testAutoConcreteResolution(): void - { - $container = new Container; - $this->assertInstanceOf( - ContainerConcreteStub::class, - $container->make(ContainerConcreteStub::class) - ); - } - - - public function testSlashesAreHandled(): void - { - $container = new Container; - $container->bind('\Foo', function() { return 'hello'; }); - $this->assertEquals('hello', $container->make('Foo')); - } - - - public function testParametersCanOverrideDependencies(): void - { - $container = new Container; - $stub = new ContainerDependentStub($mock = m::mock(IContainerContractStub::class)); - $resolved = $container->make(ContainerNestedDependentStub::class, [$stub]); - $this->assertInstanceOf(ContainerNestedDependentStub::class, $resolved); - $this->assertEquals($mock, $resolved->inner->impl); - } - - - public function testSharedConcreteResolution(): void - { - $container = new Container; - $container->singleton(ContainerConcreteStub::class); - $bindings = $container->getBindings(); - - $var1 = $container->make(ContainerConcreteStub::class); - $var2 = $container->make(ContainerConcreteStub::class); - $this->assertSame($var1, $var2); - } - - public function testSingletonIfDoesntRegisterIfBindingAlreadyRegistered(): void - { - $container = new Container; - $container->singleton('class', function () { - return new stdClass; - }); - $firstInstantiation = $container->make('class'); - $container->singletonIf('class', function () { - return new ContainerConcreteStub; - }); - $secondInstantiation = $container->make('class'); - $this->assertSame($firstInstantiation, $secondInstantiation); - } - - public function testSingletonIfDoesRegisterIfBindingNotRegisteredYet(): void - { - $container = new Container; - $container->singleton('class', function () { - return new stdClass; - }); - $container->singletonIf('otherClass', function () { - return new ContainerConcreteStub; - }); - $firstInstantiation = $container->make('otherClass'); - $secondInstantiation = $container->make('otherClass'); - $this->assertSame($firstInstantiation, $secondInstantiation); - } - - public function testAbstractToConcreteResolution(): void - { - $container = new Container; - $container->bind(IContainerContractStub::class, ContainerImplementationStub::class); - $class = $container->make(ContainerDependentStub::class); - $this->assertInstanceOf(ContainerImplementationStub::class, $class->impl); - } - - - public function testNestedDependencyResolution(): void - { - $container = new Container; - $container->bind(IContainerContractStub::class, ContainerImplementationStub::class); - $class = $container->make(ContainerNestedDependentStub::class); - $this->assertInstanceOf(ContainerDependentStub::class, $class->inner); - $this->assertInstanceOf(ContainerImplementationStub::class, $class->inner->impl); - } - - - public function testContainerIsPassedToResolvers(): void - { - $container = new Container; - $container->bind('something', function($c) { return $c; }); - $c = $container->make('something'); - $this->assertSame($c, $container); - } - - - public function testArrayAccess(): void - { - $container = new Container; - $container['something'] = function() { return 'foo'; }; - $this->assertTrue(isset($container['something'])); - $this->assertEquals('foo', $container['something']); - unset($container['something']); - $this->assertFalse(isset($container['something'])); - } - - - public function testAliases(): void - { - $container = new Container; - $container['foo'] = 'bar'; - $container->alias('foo', 'baz'); - $this->assertEquals('bar', $container->make('foo')); - $this->assertEquals('bar', $container->make('baz')); - $container->bind(['bam' => 'boom'], function() { return 'pow'; }); - $this->assertEquals('pow', $container->make('bam')); - $this->assertEquals('pow', $container->make('boom')); - $container->instance(['zoom' => 'zing'], 'wow'); - $this->assertEquals('wow', $container->make('zoom')); - $this->assertEquals('wow', $container->make('zing')); - } - - - public function testShareMethod(): void - { - $container = new Container; - $closure = $container->share(function() { return new stdClass; }); - $class1 = $closure($container); - $class2 = $closure($container); - $this->assertSame($class1, $class2); - } - - public function testBindingsCanBeOverridden(): void - { - $container = new Container; - $container['foo'] = 'bar'; - $foo = $container['foo']; - $container['foo'] = 'baz'; - $this->assertEquals('baz', $container['foo']); - } - - public function testParametersCanBePassedThroughToClosure(): void - { - $container = new Container; - $container->bind('foo', function($c, $parameters) - { - return $parameters; - }); - - $this->assertEquals([1, 2, 3], $container->make('foo', [1, 2, 3])); - } - - public function testResolutionOfDefaultParameters(): void - { - $container = new Container; - $instance = $container->make(ContainerDefaultValueStub::class); - $this->assertInstanceOf(ContainerConcreteStub::class, $instance->stub); - $this->assertEquals('taylor', $instance->default); - } - - - public function testResolvingCallbacksAreCalledForSpecificAbstracts(): void - { - $container = new Container; - $container->resolving('foo', function($object) { return $object->name = 'taylor'; }); - $container->bind('foo', function() { return new StdClass; }); - $instance = $container->make('foo'); - - $this->assertEquals('taylor', $instance->name); - } - - - public function testResolvingCallbacksAreCalled(): void - { - $container = new Container; - $container->resolvingAny(function($object) { return $object->name = 'taylor'; }); - $container->bind('foo', function() { return new StdClass; }); - $instance = $container->make('foo'); - - $this->assertEquals('taylor', $instance->name); - } - - - public function testUnsetRemoveBoundInstances(): void - { - $container = new Container; - $container->instance('object', new StdClass); - unset($container['object']); - - $this->assertFalse($container->bound('object')); - } - - - public function testReboundListeners(): void - { - unset($_SERVER['__test.rebind']); - - $container = new Container; - $container->bind('foo', function() {}); - $container->rebinding('foo', function() { $_SERVER['__test.rebind'] = true; }); - $container->bind('foo', function() {}); - - $this->assertTrue($_SERVER['__test.rebind']); - } - - - public function testReboundListenersOnInstances(): void - { - unset($_SERVER['__test.rebind']); - - $container = new Container; - $container->instance('foo', function() {}); - $container->rebinding('foo', function() { $_SERVER['__test.rebind'] = true; }); - $container->instance('foo', function() {}); - - $this->assertTrue($_SERVER['__test.rebind']); - } - - - public function testPassingSomePrimitiveParameters(): void - { - $container = new Container; - $value = $container->make(ContainerMixedPrimitiveStub::class, ['first' => 'taylor', 'last' => 'otwell']); - $this->assertInstanceOf(ContainerMixedPrimitiveStub::class, $value); - $this->assertEquals('taylor', $value->first); - $this->assertEquals('otwell', $value->last); - $this->assertInstanceOf(ContainerConcreteStub::class, $value->stub); - - $container = new Container; - $value = $container->make(ContainerMixedPrimitiveStub::class, [0 => 'taylor', 2 => 'otwell']); - $this->assertInstanceOf(ContainerMixedPrimitiveStub::class, $value); - $this->assertEquals('taylor', $value->first); - $this->assertEquals('otwell', $value->last); - $this->assertInstanceOf(ContainerConcreteStub::class, $value->stub); - } - - - public function testCreatingBoundConcreteClassPassesParameters(): void - { - $container = new Container; - $container->bind('TestAbstractClass', ContainerConstructorParameterLoggingStub::class); - $parameters = ['First', 'Second']; - $instance = $container->make('TestAbstractClass', $parameters); - $this->assertEquals($parameters, $instance->receivedParameters); - } - - - public function testInternalClassWithDefaultParameters(): void - { - $this->expectException(BindingResolutionException::class, 'Unresolvable dependency resolving [Parameter #0 [ $first ]] in class ContainerMixedPrimitiveStub'); - $container = new Container; - $parameters = []; - $container->make('ContainerMixedPrimitiveStub', $parameters); - } - - - public function testUnsetAffectsResolved(): void - { - $container = new Container; - $container->make(ContainerConcreteStub::class); - - unset($container[ContainerConcreteStub::class]); - $this->assertFalse($container->resolved(ContainerConcreteStub::class)); - } - -} - -class ContainerConcreteStub {} - -interface IContainerContractStub {} - -class ContainerImplementationStub implements IContainerContractStub {} - -class ContainerDependentStub { - public $impl; - public function __construct(IContainerContractStub $impl) - { - $this->impl = $impl; - } -} - -class ContainerNestedDependentStub { - public $inner; - public function __construct(ContainerDependentStub $inner) - { - $this->inner = $inner; - } -} - -class ContainerDefaultValueStub { - public $stub; public $default; - public function __construct(ContainerConcreteStub $stub, $default = 'taylor') - { - $this->stub = $stub; - $this->default = $default; - } -} - -class ContainerMixedPrimitiveStub { - public function __construct(public $first, public ContainerConcreteStub $stub, public $last) - {} -} - -class ContainerConstructorParameterLoggingStub { - public $receivedParameters; - - public function __construct($first, $second) - { - $this->receivedParameters = func_get_args(); - } -} - -class ContainerLazyExtendStub { - public static $initialized = false; - public function init(): void - { static::$initialized = true; } -} diff --git a/tests/Container/ContainerNewTest.php b/tests/Container/ContainerNewTest.php deleted file mode 100644 index d4fd2cfea..000000000 --- a/tests/Container/ContainerNewTest.php +++ /dev/null @@ -1,690 +0,0 @@ -assertSame($container, Container::getInstance()); - - Container::setInstance(null); - - $container2 = Container::getInstance(); - - $this->assertInstanceOf(Container::class, $container2); - $this->assertNotSame($container, $container2); - } - - public function testClosureResolution(): void - { - $container = new Container; - $container->bind('name', function () { - return 'Taylor'; - }); - $this->assertSame('Taylor', $container->make('name')); - } - - public function testBindIfDoesntRegisterIfServiceAlreadyRegistered(): void - { - $container = new Container; - $container->bind('name', function () { - return 'Taylor'; - }); - $container->bindIf('name', function () { - return 'Dayle'; - }); - - $this->assertSame('Taylor', $container->make('name')); - } - - public function testBindIfDoesRegisterIfServiceNotRegisteredYet(): void - { - $container = new Container; - $container->bind('surname', function () { - return 'Taylor'; - }); - $container->bindIf('name', function () { - return 'Dayle'; - }); - - $this->assertSame('Dayle', $container->make('name')); - } - - public function testSingletonIfDoesntRegisterIfBindingAlreadyRegistered(): void - { - $container = new Container; - $container->singleton('class', function () { - return new stdClass; - }); - $firstInstantiation = $container->make('class'); - $container->singletonIf('class', function () { - return new ContainerNewConcreteStub; - }); - $secondInstantiation = $container->make('class'); - $this->assertSame($firstInstantiation, $secondInstantiation); - } - - public function testSingletonIfDoesRegisterIfBindingNotRegisteredYet(): void - { - $container = new Container; - $container->singleton('class', function () { - return new stdClass; - }); - $container->singletonIf('otherClass', function () { - return new ContainerNewConcreteStub; - }); - $firstInstantiation = $container->make('otherClass'); - $secondInstantiation = $container->make('otherClass'); - $this->assertSame($firstInstantiation, $secondInstantiation); - } - - public function testSharedClosureResolution(): void - { - $container = new Container; - $container->singleton('class', function () { - return new stdClass; - }); - $firstInstantiation = $container->make('class'); - $secondInstantiation = $container->make('class'); - $this->assertSame($firstInstantiation, $secondInstantiation); - } - - public function testAutoConcreteResolution(): void - { - $container = new Container; - $this->assertInstanceOf(ContainerNewConcreteStub::class, $container->make(ContainerNewConcreteStub::class)); - } - - public function testSharedConcreteResolution(): void - { - $container = new Container; - $container->singleton(ContainerNewConcreteStub::class); - - $var1 = $container->make(ContainerNewConcreteStub::class); - $var2 = $container->make(ContainerNewConcreteStub::class); - $this->assertSame($var1, $var2); - } - - public function testBindFailsLoudlyWithInvalidArgument(): void - { - $this->expectException(TypeError::class); - $container = new Container; - - $concrete = new ContainerNewConcreteStub; - $container->bind(ContainerNewConcreteStub::class, $concrete); - } - - public function testAbstractToConcreteResolution(): void - { - $container = new Container; - $container->bind(IContainerNewContractStub::class, ContainerNewImplementationStub::class); - $class = $container->make(ContainerNewDependentStub::class); - $this->assertInstanceOf(ContainerNewImplementationStub::class, $class->impl); - } - - public function testNestedDependencyResolution(): void - { - $container = new Container; - $container->bind(IContainerNewContractStub::class, ContainerNewImplementationStub::class); - $class = $container->make(ContainerNewNestedDependentStub::class); - $this->assertInstanceOf(ContainerNewDependentStub::class, $class->inner); - $this->assertInstanceOf(ContainerNewImplementationStub::class, $class->inner->impl); - } - - public function testContainerIsPassedToResolvers(): void - { - $container = new Container; - $container->bind('something', function ($c) { - return $c; - }); - $c = $container->make('something'); - $this->assertSame($c, $container); - } - - public function testArrayAccess(): void - { - $container = new Container; - $container['something'] = function () { - return 'foo'; - }; - $this->assertTrue(isset($container['something'])); - $this->assertSame('foo', $container['something']); - unset($container['something']); - $this->assertFalse(isset($container['something'])); - } - - public function testAliases(): void - { - $container = new Container; - $container['foo'] = 'bar'; - $container->alias('foo', 'baz'); - $container->alias('baz', 'bat'); - $this->assertSame('bar', $container->make('foo')); - $this->assertSame('bar', $container->make('baz')); - $this->assertSame('bar', $container->make('bat')); - } - - public function testAliasesWithArrayOfParameters(): void - { - $container = new Container; - $container->bind('foo', function ($app, $config) { - return $config; - }); - $container->alias('foo', 'baz'); - $this->assertEquals([1, 2, 3], $container->make('baz', [1, 2, 3])); - } - - public function testBindingsCanBeOverridden(): void - { - $container = new Container; - $container['foo'] = 'bar'; - $container['foo'] = 'baz'; - $this->assertSame('baz', $container['foo']); - } - - public function testBindingAnInstanceReturnsTheInstance(): void - { - $container = new Container; - - $bound = new stdClass; - $resolved = $container->instance('foo', $bound); - - $this->assertSame($bound, $resolved); - } - - public function testBindingAnInstanceAsShared(): void - { - $container = new Container; - $bound = new stdClass; - $container->instance('foo', $bound); - $object = $container->make('foo'); - $this->assertSame($bound, $object); - } - - public function testResolutionOfDefaultParameters(): void - { - $container = new Container; - $instance = $container->make(ContainerNewDefaultValueStub::class); - $this->assertInstanceOf(ContainerNewConcreteStub::class, $instance->stub); - $this->assertSame('taylor', $instance->default); - } - - public function testUnsetRemoveBoundInstances(): void - { - $container = new Container; - $container->instance('object', new stdClass); - unset($container['object']); - - $this->assertFalse($container->bound('object')); - } - - public function testBoundInstanceAndAliasCheckViaArrayAccess(): void - { - $container = new Container; - $container->instance('object', new stdClass); - $container->alias('object', 'alias'); - - $this->assertTrue(isset($container['object'])); - $this->assertTrue(isset($container['alias'])); - } - - public function testReboundListeners(): void - { - unset($_SERVER['__test.rebind']); - - $container = new Container; - $container->bind('foo', function () { - // - }); - $container->rebinding('foo', function () { - $_SERVER['__test.rebind'] = true; - }); - $container->bind('foo', function () { - // - }); - - $this->assertTrue($_SERVER['__test.rebind']); - } - - public function testReboundListenersOnInstances(): void - { - unset($_SERVER['__test.rebind']); - - $container = new Container; - $container->instance('foo', function () { - // - }); - $container->rebinding('foo', function () { - $_SERVER['__test.rebind'] = true; - }); - $container->instance('foo', function () { - // - }); - - $this->assertTrue($_SERVER['__test.rebind']); - } - - public function testReboundListenersOnInstancesOnlyFiresIfWasAlreadyBound(): void - { - $_SERVER['__test.rebind'] = false; - - $container = new Container; - $container->rebinding('foo', function () { - $_SERVER['__test.rebind'] = true; - }); - $container->instance('foo', function () { - // - }); - - $this->assertFalse($_SERVER['__test.rebind']); - } - - public function testInternalClassWithDefaultParameters(): void - { - $this->expectException(BindingResolutionException::class); - $this->expectExceptionMessage('Unresolvable dependency resolving [Parameter #0 [ $first ]] in class Illuminate\Tests\Container\ContainerNewMixedPrimitiveStub'); - - $container = new Container; - $container->make(ContainerNewMixedPrimitiveStub::class, []); - } - - public function testBindingResolutionExceptionMessage(): void - { - $this->expectException(BindingResolutionException::class); - $this->expectExceptionMessage('Target [Illuminate\Tests\Container\IContainerNewContractStub] is not instantiable.'); - - $container = new Container; - $container->make(IContainerNewContractStub::class, []); - } - - public function testBindingResolutionExceptionMessageIncludesBuildStack(): void - { - $this->expectException(BindingResolutionException::class); - $this->expectExceptionMessage('Target [Illuminate\Tests\Container\IContainerNewContractStub] is not instantiable while building [Illuminate\Tests\Container\ContainerNewDependentStub].'); - - $container = new Container; - $container->make(ContainerNewDependentStub::class, []); - } - - public function testBindingResolutionExceptionMessageWhenClassDoesNotExist(): void - { - $this->expectException(BindingResolutionException::class); - $this->expectExceptionMessage('Target class [Foo\Bar\Baz\DummyClass] does not exist.'); - - $container = new Container; - $container->build('Foo\Bar\Baz\DummyClass'); - } - - public function testForgetInstanceForgetsInstance(): void - { - $container = new Container; - $containerConcreteStub = new ContainerNewConcreteStub; - $container->instance(ContainerNewConcreteStub::class, $containerConcreteStub); - $this->assertTrue($container->isShared(ContainerNewConcreteStub::class)); - $container->forgetInstance(ContainerNewConcreteStub::class); - $this->assertFalse($container->isShared(ContainerNewConcreteStub::class)); - } - - public function testForgetInstancesForgetsAllInstances(): void - { - $container = new Container; - $containerConcreteStub1 = new ContainerNewConcreteStub; - $containerConcreteStub2 = new ContainerNewConcreteStub; - $containerConcreteStub3 = new ContainerNewConcreteStub; - $container->instance('Instance1', $containerConcreteStub1); - $container->instance('Instance2', $containerConcreteStub2); - $container->instance('Instance3', $containerConcreteStub3); - $this->assertTrue($container->isShared('Instance1')); - $this->assertTrue($container->isShared('Instance2')); - $this->assertTrue($container->isShared('Instance3')); - $container->forgetInstances(); - $this->assertFalse($container->isShared('Instance1')); - $this->assertFalse($container->isShared('Instance2')); - $this->assertFalse($container->isShared('Instance3')); - } - - public function testContainerFlushFlushesAllBindingsAliasesAndResolvedInstances(): void - { - $container = new Container; - $container->bind('ConcreteStub', function () { - return new ContainerNewConcreteStub; - }, true); - $container->alias('ConcreteStub', 'ContainerConcreteStub'); - $container->make('ConcreteStub'); - $this->assertTrue($container->resolved('ConcreteStub')); - $this->assertTrue($container->isAlias('ContainerConcreteStub')); - $this->assertArrayHasKey('ConcreteStub', $container->getBindings()); - $this->assertTrue($container->isShared('ConcreteStub')); - $container->flush(); - $this->assertFalse($container->resolved('ConcreteStub')); - $this->assertFalse($container->isAlias('ContainerConcreteStub')); - $this->assertEmpty($container->getBindings()); - $this->assertFalse($container->isShared('ConcreteStub')); - } - - public function testResolvedResolvesAliasToBindingNameBeforeChecking(): void - { - $container = new Container; - $container->bind('ConcreteStub', function () { - return new ContainerNewConcreteStub; - }, true); - $container->alias('ConcreteStub', 'foo'); - - $this->assertFalse($container->resolved('ConcreteStub')); - $this->assertFalse($container->resolved('foo')); - - $container->make('ConcreteStub'); - - $this->assertTrue($container->resolved('ConcreteStub')); - $this->assertTrue($container->resolved('foo')); - } - - public function testGetAlias(): void - { - $container = new Container; - $container->alias('ConcreteStub', 'foo'); - $this->assertSame('ConcreteStub', $container->getAlias('foo')); - } - - public function testItThrowsExceptionWhenAbstractIsSameAsAlias(): void - { - $this->expectException('LogicException'); - $this->expectExceptionMessage('[name] is aliased to itself.'); - - $container = new Container; - $container->alias('name', 'name'); - } - - public function testContainerGetFactory(): void - { - $container = new Container; - $container->bind('name', function () { - return 'Taylor'; - }); - - $factory = $container->factory('name'); - $this->assertEquals($container->make('name'), $factory()); - } - - public function testMakeWithMethodIsAnAliasForMakeMethod(): void - { - $mock = $this->getMockBuilder(Container::class) - ->onlyMethods(['make']) - ->getMock(); - - $mock->expects($this->once()) - ->method('make') - ->with(ContainerNewDefaultValueStub::class, ['default' => 'laurence']) - ->willReturn(new stdClass); - - $result = $mock->makeWith(ContainerNewDefaultValueStub::class, ['default' => 'laurence']); - - $this->assertInstanceOf(stdClass::class, $result); - } - - public function testResolvingWithArrayOfParameters(): void - { - $container = new Container; - $instance = $container->make(ContainerNewDefaultValueStub::class, ['default' => 'adam']); - $this->assertSame('adam', $instance->default); - - $instance = $container->make(ContainerNewDefaultValueStub::class); - $this->assertSame('taylor', $instance->default); - - $container->bind('foo', function ($app, $config) { - return $config; - }); - - $this->assertEquals([1, 2, 3], $container->make('foo', [1, 2, 3])); - } - - public function testResolvingWithUsingAnInterface(): void - { - $container = new Container; - $container->bind(IContainerNewContractStub::class, ContainerNewInjectVariableStubWithInterfaceImplementation::class); - $instance = $container->make(IContainerNewContractStub::class, ['something' => 'laurence']); - $this->assertSame('laurence', $instance->something); - } - - public function testNestedParameterOverride(): void - { - $container = new Container; - $container->bind('foo', function ($app, $config) { - return $app->make('bar', ['name' => 'Taylor']); - }); - $container->bind('bar', function ($app, $config) { - return $config; - }); - - $this->assertEquals(['name' => 'Taylor'], $container->make('foo', ['something'])); - } - - public function testNestedParametersAreResetForFreshMake(): void - { - $container = new Container; - - $container->bind('foo', function ($app, $config) { - return $app->make('bar'); - }); - - $container->bind('bar', function ($app, $config) { - return $config; - }); - - $this->assertEquals([], $container->make('foo', ['something'])); - } - - public function testSingletonBindingsNotRespectedWithMakeParameters(): void - { - $container = new Container; - - $container->singleton('foo', function ($app, $config) { - return $config; - }); - - $this->assertEquals(['name' => 'taylor'], $container->make('foo', ['name' => 'taylor'])); - $this->assertEquals(['name' => 'abigail'], $container->make('foo', ['name' => 'abigail'])); - } - - public function testCanBuildWithoutParameterStackWithNoConstructors(): void - { - $container = new Container; - $this->assertInstanceOf(ContainerNewConcreteStub::class, $container->build(ContainerNewConcreteStub::class)); - } - - public function testCanBuildWithoutParameterStackWithConstructors(): void - { - $container = new Container; - $container->bind(IContainerNewContractStub::class, ContainerNewImplementationStub::class); - $this->assertInstanceOf(ContainerNewDependentStub::class, $container->build(ContainerNewDependentStub::class)); - } - - public function testContainerKnowsEntry(): void - { - $container = new Container; - $container->bind(IContainerNewContractStub::class, ContainerNewImplementationStub::class); - $this->assertTrue($container->has(IContainerNewContractStub::class)); - } - - public function testContainerCanBindAnyWord(): void - { - $container = new Container; - $container->bind('Taylor', stdClass::class); - $this->assertInstanceOf(stdClass::class, $container->get('Taylor')); - } - - public function testContainerCanDynamicallySetService(): void - { - $container = new Container; - $this->assertFalse(isset($container['name'])); - $container['name'] = 'Taylor'; - $this->assertTrue(isset($container['name'])); - $this->assertSame('Taylor', $container['name']); - } - - public function testUnknownEntryThrowsException(): void - { - $this->expectException(EntryNotFoundException::class); - - $container = new Container; - $container->get('Taylor'); - } - - public function testBoundEntriesThrowsContainerExceptionWhenNotResolvable(): void - { - $this->expectException(BindingResolutionException::class); - - $container = new Container; - $container->bind('Taylor', IContainerNewContractStub::class); - - $container->get('Taylor'); - } - - public function testContainerCanResolveClasses(): void - { - $container = new Container; - $class = $container->get(ContainerNewConcreteStub::class); - - $this->assertInstanceOf(ContainerNewConcreteStub::class, $class); - } - - // public function testContainerCanCatchCircularDependency() - // { - // $this->expectException(\Illuminate\Contracts\Container\CircularDependencyException::class); - - // $container = new Container; - // $container->get(CircularAStub::class); - // } -} - -class CircularAStub -{ - public function __construct(CircularBStub $b) - { - // - } -} - -class CircularBStub -{ - public function __construct(CircularCStub $c) - { - // - } -} - -class CircularCStub -{ - public function __construct(CircularAStub $a) - { - // - } -} - -class ContainerNewConcreteStub -{ - // -} - -interface IContainerNewContractStub -{ - // -} - -class ContainerNewImplementationStub implements IContainerNewContractStub -{ - // -} - -class ContainerNewImplementationStubTwo implements IContainerNewContractStub -{ - // -} - -class ContainerNewDependentStub -{ - public $impl; - - public function __construct(IContainerNewContractStub $impl) - { - $this->impl = $impl; - } -} - -class ContainerNewNestedDependentStub -{ - public $inner; - - public function __construct(ContainerNewDependentStub $inner) - { - $this->inner = $inner; - } -} - -class ContainerNewDefaultValueStub -{ - public $stub; - public $default; - - public function __construct(ContainerNewConcreteStub $stub, $default = 'taylor') - { - $this->stub = $stub; - $this->default = $default; - } -} - -class ContainerNewMixedPrimitiveStub -{ - public $first; - public $last; - public $stub; - - public function __construct($first, ContainerNewConcreteStub $stub, $last) - { - $this->stub = $stub; - $this->last = $last; - $this->first = $first; - } -} - -class ContainerNewInjectVariableStub -{ - public $something; - - public function __construct(ContainerNewConcreteStub $concrete, $something) - { - $this->something = $something; - } -} - -class ContainerNewInjectVariableStubWithInterfaceImplementation implements IContainerNewContractStub -{ - public $something; - - public function __construct(ContainerNewConcreteStub $concrete, $something) - { - $this->something = $something; - } -} \ No newline at end of file diff --git a/tests/Container/ContainerResolveNonInstantiableTest.php b/tests/Container/ContainerResolveNonInstantiableTest.php deleted file mode 100644 index 2dae6b206..000000000 --- a/tests/Container/ContainerResolveNonInstantiableTest.php +++ /dev/null @@ -1,75 +0,0 @@ -make(ParentClass::class, ['i' => 42]); - - $this->assertSame(42, $object->i); - } - - public function testResolvingNonInstantiableWithVariadicRemovesWiths(): void - { - $container = new Container; - $parent = $container->make(VariadicParentClass::class, ['i' => 42]); - - $this->assertCount(0, $parent->child->objects); - $this->assertSame(42, $parent->i); - } -} - -interface TestInterface -{ -} - -class ParentClass -{ - /** - * @var int - */ - public $i; - - public function __construct(?TestInterface $testObject = null, int $i = 0) - { - $this->i = $i; - } -} - -class VariadicParentClass -{ - /** - * @var \Illuminate\Tests\Container\ChildClass - */ - public $child; - - /** - * @var int - */ - public $i; - - public function __construct(ChildClass $child, int $i = 0) - { - $this->child = $child; - $this->i = $i; - } -} - -class ChildClass -{ - /** - * @var array - */ - public $objects; - - public function __construct(TestInterface ...$objects) - { - $this->objects = $objects; - } -} diff --git a/tests/Container/ContainerTaggingTest.php b/tests/Container/ContainerTaggingTest.php deleted file mode 100644 index 4b5ca8482..000000000 --- a/tests/Container/ContainerTaggingTest.php +++ /dev/null @@ -1,105 +0,0 @@ -tag(ContainerImplementationTaggedStub::class, 'foo', 'bar'); - $container->tag(ContainerImplementationTaggedStubTwo::class, ['foo']); - - $this->assertCount(1, $container->tagged('bar')); - $this->assertCount(2, $container->tagged('foo')); - - $fooResults = []; - foreach ($container->tagged('foo') as $foo) { - $fooResults[] = $foo; - } - - $barResults = []; - foreach ($container->tagged('bar') as $bar) { - $barResults[] = $bar; - } - - $this->assertInstanceOf(ContainerImplementationTaggedStub::class, $fooResults[0]); - $this->assertInstanceOf(ContainerImplementationTaggedStub::class, $barResults[0]); - $this->assertInstanceOf(ContainerImplementationTaggedStubTwo::class, $fooResults[1]); - - $container = new Container; - $container->tag([ContainerImplementationTaggedStub::class, ContainerImplementationTaggedStubTwo::class], ['foo']); - $this->assertCount(2, $container->tagged('foo')); - - $fooResults = []; - foreach ($container->tagged('foo') as $foo) { - $fooResults[] = $foo; - } - - $this->assertInstanceOf(ContainerImplementationTaggedStub::class, $fooResults[0]); - $this->assertInstanceOf(ContainerImplementationTaggedStubTwo::class, $fooResults[1]); - - $this->assertCount(0, $container->tagged('this_tag_does_not_exist')); - } - - public function testTaggedServicesAreLazyLoaded(): void - { - $container = $this->createPartialMock(Container::class, ['make']); - $container->expects($this->once())->method('make')->willReturn(new ContainerImplementationTaggedStub); - - $container->tag(ContainerImplementationTaggedStub::class, ['foo']); - $container->tag(ContainerImplementationTaggedStubTwo::class, ['foo']); - - $fooResults = []; - foreach ($container->tagged('foo') as $foo) { - $fooResults[] = $foo; - break; - } - - $this->assertCount(2, $container->tagged('foo')); - $this->assertInstanceOf(ContainerImplementationTaggedStub::class, $fooResults[0]); - } - - public function testLazyLoadedTaggedServicesCanBeLoopedOverMultipleTimes(): void - { - $container = new Container; - $container->tag(ContainerImplementationTaggedStub::class, 'foo'); - $container->tag(ContainerImplementationTaggedStubTwo::class, ['foo']); - - $services = $container->tagged('foo'); - - $fooResults = []; - foreach ($services as $foo) { - $fooResults[] = $foo; - } - - $this->assertInstanceOf(ContainerImplementationTaggedStub::class, $fooResults[0]); - $this->assertInstanceOf(ContainerImplementationTaggedStubTwo::class, $fooResults[1]); - - $fooResults = []; - foreach ($services as $foo) { - $fooResults[] = $foo; - } - - $this->assertInstanceOf(ContainerImplementationTaggedStub::class, $fooResults[0]); - $this->assertInstanceOf(ContainerImplementationTaggedStubTwo::class, $fooResults[1]); - } -} - -interface IContainerTaggedContractStub -{ - // -} - -class ContainerImplementationTaggedStub implements IContainerTaggedContractStub -{ - // -} - -class ContainerImplementationTaggedStubTwo implements IContainerTaggedContractStub -{ - // -} diff --git a/tests/Container/ResolvingCallbackTest.php b/tests/Container/ResolvingCallbackTest.php deleted file mode 100644 index 58a93bf9e..000000000 --- a/tests/Container/ResolvingCallbackTest.php +++ /dev/null @@ -1,498 +0,0 @@ -resolving('foo', function ($object) { - return $object->name = 'taylor'; - }); - $container->bind('foo', function () { - return new stdClass; - }); - $instance = $container->make('foo'); - - $this->assertSame('taylor', $instance->name); - } - - public function testResolvingCallbacksAreCalled(): void - { - $container = new Container; - $container->resolving(function ($object) { - return $object->name = 'taylor'; - }); - $container->bind('foo', function () { - return new stdClass; - }); - $instance = $container->make('foo'); - - $this->assertSame('taylor', $instance->name); - } - - public function testResolvingCallbacksAreCalledForType(): void - { - $container = new Container; - $container->resolving(stdClass::class, function ($object) { - return $object->name = 'taylor'; - }); - $container->bind('foo', function () { - return new stdClass; - }); - $instance = $container->make('foo'); - - $this->assertSame('taylor', $instance->name); - } - - public function testResolvingCallbacksShouldBeFiredWhenCalledWithAliases(): void - { - $container = new Container; - $container->alias(stdClass::class, 'std'); - $container->resolving('std', function ($object) { - return $object->name = 'taylor'; - }); - $container->bind('foo', function () { - return new stdClass; - }); - $instance = $container->make('foo'); - - $this->assertSame('taylor', $instance->name); - } - - public function testResolvingCallbacksAreCalledOnceForImplementation(): void - { - $container = new Container; - - $callCounter = 0; - $container->resolving(ResolvingContractStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(1, $callCounter); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(2, $callCounter); - } - - public function testGlobalResolvingCallbacksAreCalledOnceForImplementation(): void - { - $container = new Container; - - $callCounter = 0; - $container->resolving(function () use (&$callCounter) { - $callCounter++; - }); - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(1, $callCounter); - - $container->make(ResolvingContractStub::class); - $this->assertEquals(2, $callCounter); - } - - public function testResolvingCallbacksAreCalledOnceForSingletonConcretes(): void - { - $container = new Container; - - $callCounter = 0; - $container->resolving(ResolvingContractStub::class, function ($object) use (&$callCounter) { - $callCounter++; - }); - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - $container->bind(ResolvingImplementationStub::class); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(1, $callCounter); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(2, $callCounter); - - $container->make(ResolvingContractStub::class); - $this->assertEquals(3, $callCounter); - } - - public function testResolvingCallbacksCanStillBeAddedAfterTheFirstResolution(): void - { - $container = new Container; - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - - $container->make(ResolvingImplementationStub::class); - - $callCounter = 0; - $container->resolving(ResolvingContractStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(1, $callCounter); - } - - public function testResolvingCallbacksAreCanceledWhenInterfaceGetsBoundToSomeOtherConcrete(): void - { - $container = new Container; - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - - $callCounter = 0; - $container->resolving(ResolvingImplementationStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->make(ResolvingContractStub::class); - $this->assertEquals(1, $callCounter); - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStubTwo::class); - $container->make(ResolvingContractStub::class); - $this->assertEquals(1, $callCounter); - } - - public function testResolvingCallbacksAreCalledOnceForStringAbstractions(): void - { - $container = new Container; - - $callCounter = 0; - $container->resolving('foo', function () use (&$callCounter) { - $callCounter++; - }); - - $container->bind('foo', ResolvingImplementationStub::class); - - $container->make('foo'); - $this->assertEquals(1, $callCounter); - - $container->make('foo'); - $this->assertEquals(2, $callCounter); - } - - public function testResolvingCallbacksForConcretesAreCalledOnceForStringAbstractions(): void - { - $container = new Container; - - $callCounter = 0; - $container->resolving(ResolvingImplementationStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->bind('foo', ResolvingImplementationStub::class); - $container->bind('bar', ResolvingImplementationStub::class); - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(1, $callCounter); - - $container->make('foo'); - $this->assertEquals(2, $callCounter); - - $container->make('bar'); - $this->assertEquals(3, $callCounter); - - $container->make(ResolvingContractStub::class); - $this->assertEquals(4, $callCounter); - } - - public function testResolvingCallbacksAreCalledOnceForImplementation2(): void - { - $container = new Container; - - $callCounter = 0; - $container->resolving(ResolvingContractStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->bind(ResolvingContractStub::class, function () { - return new ResolvingImplementationStub; - }); - - $container->make(ResolvingContractStub::class); - $this->assertEquals(1, $callCounter); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(2, $callCounter); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(3, $callCounter); - - $container->make(ResolvingContractStub::class); - $this->assertEquals(4, $callCounter); - } - - public function testRebindingDoesNotAffectResolvingCallbacks(): void - { - $container = new Container; - - $callCounter = 0; - $container->resolving(ResolvingContractStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - $container->bind(ResolvingContractStub::class, function () { - return new ResolvingImplementationStub; - }); - - $container->make(ResolvingContractStub::class); - $this->assertEquals(1, $callCounter); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(2, $callCounter); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(3, $callCounter); - - $container->make(ResolvingContractStub::class); - $this->assertEquals(4, $callCounter); - } - - public function testParametersPassedIntoResolvingCallbacks(): void - { - $container = new Container; - - $container->resolving(ResolvingContractStub::class, function ($obj, $app) use ($container) { - $this->assertInstanceOf(ResolvingContractStub::class, $obj); - $this->assertInstanceOf(ResolvingImplementationStubTwo::class, $obj); - $this->assertSame($container, $app); - }); - - $container->afterResolving(ResolvingContractStub::class, function ($obj, $app) use ($container) { - $this->assertInstanceOf(ResolvingContractStub::class, $obj); - $this->assertInstanceOf(ResolvingImplementationStubTwo::class, $obj); - $this->assertSame($container, $app); - }); - - $container->afterResolving(function ($obj, $app) use ($container) { - $this->assertInstanceOf(ResolvingContractStub::class, $obj); - $this->assertInstanceOf(ResolvingImplementationStubTwo::class, $obj); - $this->assertSame($container, $app); - }); - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStubTwo::class); - $container->make(ResolvingContractStub::class); - } - - public function testResolvingCallbacksAreCallWhenRebindHappenForResolvedAbstract(): void - { - $container = new Container; - - $callCounter = 0; - $container->resolving(ResolvingContractStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - - $container->make(ResolvingContractStub::class); - $this->assertEquals(1, $callCounter); - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStubTwo::class); - $this->assertEquals(2, $callCounter); - - $container->make(ResolvingImplementationStubTwo::class); - $this->assertEquals(3, $callCounter); - - $container->bind(ResolvingContractStub::class, function () { - return new ResolvingImplementationStubTwo; - }); - $this->assertEquals(4, $callCounter); - - $container->make(ResolvingContractStub::class); - $this->assertEquals(5, $callCounter); - } - - public function testRebindingDoesNotAffectMultipleResolvingCallbacks(): void - { - $container = new Container; - - $callCounter = 0; - - $container->resolving(ResolvingContractStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->resolving(ResolvingImplementationStubTwo::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - - // it should call the callback for interface - $container->make(ResolvingContractStub::class); - $this->assertEquals(1, $callCounter); - - // it should call the callback for interface - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(2, $callCounter); - - // should call the callback for the interface it implements - // plus the callback for ResolvingImplementationStubTwo. - $container->make(ResolvingImplementationStubTwo::class); - $this->assertEquals(4, $callCounter); - } - - public function testResolvingCallbacksAreCalledForInterfaces(): void - { - $container = new Container; - - $callCounter = 0; - $container->resolving(ResolvingContractStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - - $container->make(ResolvingContractStub::class); - - $this->assertEquals(1, $callCounter); - } - - public function testResolvingCallbacksAreCalledForConcretesWhenAttachedOnInterface(): void - { - $container = new Container; - - $callCounter = 0; - $container->resolving(ResolvingImplementationStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - - $container->make(ResolvingContractStub::class); - $this->assertEquals(1, $callCounter); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(2, $callCounter); - } - - public function testResolvingCallbacksAreCalledForConcretesWhenAttachedOnConcretes(): void - { - $container = new Container; - - $callCounter = 0; - $container->resolving(ResolvingImplementationStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - - $container->make(ResolvingContractStub::class); - $this->assertEquals(1, $callCounter); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(2, $callCounter); - } - - public function testResolvingCallbacksAreCalledForConcretesWithNoBinding(): void - { - $container = new Container; - - $callCounter = 0; - $container->resolving(ResolvingImplementationStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(1, $callCounter); - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(2, $callCounter); - } - - public function testResolvingCallbacksAreCalledForInterFacesWithNoBinding(): void - { - $container = new Container; - - $callCounter = 0; - $container->resolving(ResolvingContractStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(1, $callCounter); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(2, $callCounter); - } - - public function testAfterResolvingCallbacksAreCalledOnceForImplementation(): void - { - $container = new Container; - - $callCounter = 0; - $container->afterResolving(ResolvingContractStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(1, $callCounter); - - $container->make(ResolvingContractStub::class); - $this->assertEquals(2, $callCounter); - } - - public function testBeforeResolvingCallbacksAreCalled(): void - { - // Given a call counter initialized to zero. - $container = new Container; - $callCounter = 0; - - // And a contract/implementation stub binding. - $container->bind(ResolvingContractStub::class, ResolvingImplementationStub::class); - - // When we add a before resolving callback that increment the counter by one. - $container->beforeResolving(ResolvingContractStub::class, function () use (&$callCounter) { - $callCounter++; - }); - - // Then resolving the implementation stub increases the counter by one. - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(1, $callCounter); - - // And resolving the contract stub increases the counter by one. - $container->make(ResolvingContractStub::class); - $this->assertEquals(2, $callCounter); - } - - public function testGlobalBeforeResolvingCallbacksAreCalled(): void - { - // Given a call counter initialized to zero. - $container = new Container; - $callCounter = 0; - - // When we add a global before resolving callback that increment that counter by one. - $container->beforeResolving(function () use (&$callCounter) { - $callCounter++; - }); - - // Then resolving anything increases the counter by one. - $container->make(ResolvingImplementationStub::class); - $this->assertEquals(1, $callCounter); - } -} - -interface ResolvingContractStub -{ - // -} - -class ResolvingImplementationStub implements ResolvingContractStub -{ - // -} - -class ResolvingImplementationStubTwo implements ResolvingContractStub -{ - // -} diff --git a/tests/Container/RewindableGeneratorTest.php b/tests/Container/RewindableGeneratorTest.php deleted file mode 100644 index b65c3498e..000000000 --- a/tests/Container/RewindableGeneratorTest.php +++ /dev/null @@ -1,41 +0,0 @@ -assertCount(999, $generator); - } - - public function testCountUsesProvidedValueAsCallback(): void - { - $called = 0; - - $generator = new RewindableGenerator(function () { - yield 'foo'; - }, function () use (&$called) { - $called++; - - return 500; - }); - - // the count callback is called lazily - $this->assertSame(0, $called); - - $this->assertCount(500, $generator); - - count($generator); - - // the count callback is called only once - $this->assertSame(1, $called); - } -} diff --git a/tests/Cookie/CookieTest.php b/tests/Cookie/CookieTest.php deleted file mode 100755 index c4128e37d..000000000 --- a/tests/Cookie/CookieTest.php +++ /dev/null @@ -1,139 +0,0 @@ -getCreator(); - $cookie->setDefaultPathAndDomain('foo', 'bar'); - $c = $cookie->make('color', 'blue', 10, '/path', '/domain', true, false); - $this->assertEquals('blue', $c->getValue()); - $this->assertFalse($c->isHttpOnly()); - $this->assertTrue($c->isSecure()); - $this->assertEquals('/domain', $c->getDomain()); - $this->assertEquals('/path', $c->getPath()); - - $c2 = $cookie->forever('color', 'blue', '/path', '/domain', true, false); - $this->assertEquals('blue', $c2->getValue()); - $this->assertFalse($c2->isHttpOnly()); - $this->assertTrue($c2->isSecure()); - $this->assertEquals('/domain', $c2->getDomain()); - $this->assertEquals('/path', $c2->getPath()); - - $c3 = $cookie->forget('color'); - $this->assertNull($c3->getValue()); - $this->assertTrue($c3->getExpiresTime() < time()); - } - - - public function testCookiesAreCreatedWithProperOptionsUsingDefaultPathAndDomain() - { - $cookie = $this->getCreator(); - $cookie->setDefaultPathAndDomain('/path', '/domain'); - $c = $cookie->make('color', 'blue', 10, null, null, true, false); - $this->assertEquals('blue', $c->getValue()); - $this->assertFalse($c->isHttpOnly()); - $this->assertTrue($c->isSecure()); - $this->assertEquals('/domain', $c->getDomain()); - $this->assertEquals('/path', $c->getPath()); - } - - - public function testSameSiteAndRawWidening() - { - $cookie = $this->getCreator(); - - // behavior-preserving default: L4.2/Symfony effective SameSite = lax - $this->assertSame('lax', $cookie->make('a', 'b')->getSameSite()); - $this->assertFalse($cookie->make('a', 'b')->isRaw()); - - // per-cookie overrides via the widened signature - $c = $cookie->make('a', 'b', 0, null, null, null, true, true, 'strict'); - $this->assertSame('strict', $c->getSameSite()); - $this->assertTrue($c->isRaw()); - } - - - public function testQueuedCookies() - { - $cookie = $this->getCreator(); - $this->assertEmpty($cookie->getQueuedCookies()); - $this->assertFalse($cookie->hasQueued('foo')); - $cookie->queue($cookie->make('foo','bar')); - $this->assertTrue($cookie->hasQueued('foo')); - $this->assertInstanceOf(Cookie::class, $cookie->queued('foo')); - $cookie->queue('qu','ux'); - $this->assertTrue($cookie->hasQueued('qu')); - $this->assertInstanceOf(Cookie::class, $cookie->queued('qu')); - $this->assertCount(2, $cookie->getQueuedCookies()); - } - - - public function testUnqueue() - { - $cookie = $this->getCreator(); - $cookie->queue($cookie->make('foo','bar')); - $this->assertTrue($cookie->hasQueued('foo')); - $cookie->unqueue('foo'); - $this->assertEmpty($cookie->getQueuedCookies()); - $this->assertFalse($cookie->hasQueued('foo')); - } - - - public function testPathAwareQueuedCookies() - { - $cookie = $this->getCreator(); - $cookie->queue($cookie->make('foo', 'a', 0, '/a')); - $cookie->queue($cookie->make('foo', 'b', 0, '/b')); - - $this->assertCount(2, $cookie->getQueuedCookies()); - $this->assertSame('a', $cookie->queued('foo', null, '/a')->getValue()); - $this->assertSame('b', $cookie->queued('foo', null, '/b')->getValue()); - $this->assertSame('b', $cookie->queued('foo')->getValue()); - - $cookie->unqueue('foo', '/a'); - $this->assertNull($cookie->queued('foo', null, '/a')); - $this->assertSame('b', $cookie->queued('foo', null, '/b')->getValue()); - $this->assertCount(1, $cookie->getQueuedCookies()); - - $cookie->flushQueuedCookies(); - $this->assertEmpty($cookie->getQueuedCookies()); - } - - - public function testExpireQueuesForgetCookie() - { - $cookie = $this->getCreator(); - $cookie->expire('foo'); - - $this->assertTrue($cookie->hasQueued('foo')); - $queued = $cookie->queued('foo'); - $this->assertInstanceOf(Cookie::class, $queued); - $this->assertTrue($queued->getExpiresTime() < time()); - } - - - public function getCreator() - { - return new CookieJar(Request::create('/foo', 'GET'), [ - 'path' => '/path', - 'domain' => '/domain', - 'secure' => true, - 'httpOnly' => false, - ]); - } - -} diff --git a/tests/Database/DatabaseConnectionFactoryTest.php b/tests/Database/DatabaseConnectionFactoryTest.php deleted file mode 100755 index bf26ee104..000000000 --- a/tests/Database/DatabaseConnectionFactoryTest.php +++ /dev/null @@ -1,149 +0,0 @@ -getMock( - ConnectionFactory::class, - ['createConnector', 'createConnection'], - [$container = m::mock(Container::class)] - ); - $container->shouldReceive('bound')->andReturn(false); - $connector = m::mock('stdClass'); - $config = ['driver' => 'mysql', 'prefix' => 'prefix', 'database' => 'database', 'name' => 'foo']; - $pdo = new DatabaseConnectionFactoryPDOStub; - $connector->shouldReceive('connect')->once()->with($config)->andReturn($pdo); - $factory->expects($this->once())->method('createConnector')->with($config)->willReturn($connector); - $mockConnection = m::mock('stdClass'); - $passedConfig = array_merge($config, ['name' => 'foo']); - $factory->expects($this->once())->method('createConnection')->with($this->equalTo('mysql'), $this->equalTo($pdo), $this->equalTo('database'), $this->equalTo('prefix'), $this->equalTo($passedConfig))->willReturn( - $mockConnection - ); - $connection = $factory->make($config, 'foo'); - - $this->assertEquals($mockConnection, $connection); - } - - - public function testMakeCallsCreateConnectionForReadWrite() - { - $factory = $this->getMock(ConnectionFactory::class, ['createConnector', 'createConnection'], [ - $container = m::mock( - Container::class - ) - ]); - $container->shouldReceive('bound')->andReturn(false); - $connector = m::mock('stdClass'); - $config = [ - 'read' => ['database' => 'database'], - 'write' => ['database' => 'database'], - 'driver' => 'mysql', 'prefix' => 'prefix', 'name' => 'foo', - ]; - $expect = $config; - unset($expect['read']); - unset($expect['write']); - $expect['database'] = 'database'; - $pdo = new DatabaseConnectionFactoryPDOStub; - $connector->shouldReceive('connect')->twice()->with($expect)->andReturn($pdo); - $factory->expects($this->exactly(2))->method('createConnector')->with($expect)->willReturn($connector); - $mockConnection = m::mock('stdClass'); - $mockConnection->shouldReceive('setReadPdo')->once()->andReturn($mockConnection); - $passedConfig = array_merge($expect, ['name' => 'foo']); - $factory->expects($this->once())->method('createConnection')->with($this->equalTo('mysql'), $this->equalTo($pdo), $this->equalTo('database'), $this->equalTo('prefix'), $this->equalTo($passedConfig))->willReturn( - $mockConnection - ); - $connection = $factory->make($config, 'foo'); - - $this->assertEquals($mockConnection, $connection); - } - - - public function testMakeCanCallTheContainer() - { - $factory = $this->getMock(ConnectionFactory::class, ['createConnector'], [ - $container = m::mock( - Container::class - ) - ]); - $container->shouldReceive('bound')->andReturn(true); - $connector = m::mock('stdClass'); - $config = ['driver' => 'mysql', 'prefix' => 'prefix', 'database' => 'database', 'name' => 'foo']; - $pdo = new DatabaseConnectionFactoryPDOStub; - $connector->shouldReceive('connect')->once()->with($config)->andReturn($pdo); - $passedConfig = array_merge($config, ['name' => 'foo']); - $factory->expects($this->once())->method('createConnector')->with($config)->willReturn($connector); - $container->shouldReceive('make')->once()->with('db.connection.mysql', [$pdo, 'database', 'prefix', $passedConfig] - )->andReturn('foo'); - $connection = $factory->make($config, 'foo'); - - $this->assertEquals('foo', $connection); - } - - - public function testProperInstancesAreReturnedForProperDrivers() - { - $factory = new Illuminate\Database\Connectors\ConnectionFactory($container = m::mock( - Container::class - )); - $container->shouldReceive('bound')->andReturn(false); - $this->assertInstanceOf(MySqlConnector::class, $factory->createConnector(['driver' => 'mysql'])); - $this->assertInstanceOf(PostgresConnector::class, $factory->createConnector(['driver' => 'pgsql'])); - $this->assertInstanceOf(SQLiteConnector::class, $factory->createConnector(['driver' => 'sqlite'])); - $this->assertInstanceOf(SqlServerConnector::class, $factory->createConnector(['driver' => 'sqlsrv'])); - } - - - public function testIfDriverIsntSetExceptionIsThrown() - { - $this->expectException(InvalidArgumentException::class); - $factory = new Illuminate\Database\Connectors\ConnectionFactory( - $container = m::mock(Container::class) - ); - $factory->createConnector(['foo']); - } - - - public function testExceptionIsThrownOnUnsupportedDriver() - { - $this->expectException(InvalidArgumentException::class); - $factory = new Illuminate\Database\Connectors\ConnectionFactory( - $container = m::mock(Container::class) - ); - $container->shouldReceive('bound')->once()->andReturn(false); - $factory->createConnector(['driver' => 'foo']); - } - - - public function testCustomConnectorsCanBeResolvedViaContainer() - { - $factory = new Illuminate\Database\Connectors\ConnectionFactory($container = m::mock( - Container::class - )); - $container->shouldReceive('bound')->once()->with('db.connector.foo')->andReturn(true); - $container->shouldReceive('make')->once()->with('db.connector.foo')->andReturn('connector'); - - $this->assertEquals('connector', $factory->createConnector(['driver' => 'foo'])); - } - -} diff --git a/tests/Database/DatabaseConnectionTest.php b/tests/Database/DatabaseConnectionTest.php deleted file mode 100755 index 42cca2204..000000000 --- a/tests/Database/DatabaseConnectionTest.php +++ /dev/null @@ -1,333 +0,0 @@ -getMockConnection(); - $mock = m::mock(stdClass::class); - $connection->expects($this->once())->method('getDefaultQueryGrammar')->willReturn($mock); - $connection->useDefaultQueryGrammar(); - $this->assertEquals($mock, $connection->getQueryGrammar()); - } - - - public function testSettingDefaultCallsGetDefaultPostProcessor() - { - $connection = $this->getMockConnection(); - $mock = m::mock(stdClass::class); - $connection->expects($this->once())->method('getDefaultPostProcessor')->willReturn($mock); - $connection->useDefaultPostProcessor(); - $this->assertEquals($mock, $connection->getPostProcessor()); - } - - - public function testSelectOneCallsSelectAndReturnsSingleResult() - { - $connection = $this->getMockConnection(['select']); - $connection->expects($this->once())->method('select')->with('foo', ['bar' => 'baz'])->willReturn( - ['foo'] - ); - $this->assertEquals('foo', $connection->selectOne('foo', ['bar' => 'baz'])); - } - - - public function testSelectProperlyCallsPDO() - { - $pdo = $this->getMock(DatabaseConnectionTestMockPDO::class, ['prepare']); - $writePdo = $this->getMock(DatabaseConnectionTestMockPDO::class, ['prepare']); - $writePdo->expects($this->never())->method('prepare'); - $statement = $this->getMock('PDOStatement', ['execute', 'fetchAll']); - $statement->expects($this->once())->method('execute')->with($this->equalTo(['foo' => 'bar'])); - $statement->expects($this->once())->method('fetchAll')->willReturn(['boom']); - $pdo->expects($this->once())->method('prepare')->with('foo')->willReturn($statement); - $mock = $this->getMockConnection(['prepareBindings'], $writePdo); - $mock->setReadPdo($pdo); - $mock->expects($this->once())->method('prepareBindings')->with($this->equalTo(['foo' => 'bar']))->willReturn( - ['foo' => 'bar'] - ); - $results = $mock->select('foo', ['foo' => 'bar']); - $this->assertEquals(['boom'], $results); - $log = $mock->getQueryLog(); - $this->assertEquals('foo', $log[0]['query']); - $this->assertEquals(['foo' => 'bar'], $log[0]['bindings']); - $this->assertIsNumeric($log[0]['time']); - } - - - public function testInsertCallsTheStatementMethod() - { - $connection = $this->getMockConnection(['statement']); - $connection->expects($this->once())->method('statement')->with($this->equalTo('foo'), $this->equalTo(['bar']))->willReturn( - 'baz' - ); - $results = $connection->insert('foo', ['bar']); - $this->assertEquals('baz', $results); - } - - - public function testUpdateCallsTheAffectingStatementMethod() - { - $connection = $this->getMockConnection(['affectingStatement']); - $connection->expects($this->once())->method('affectingStatement')->with($this->equalTo('foo'), $this->equalTo( - ['bar'] - ))->willReturn( - 'baz' - ); - $results = $connection->update('foo', ['bar']); - $this->assertEquals('baz', $results); - } - - - public function testDeleteCallsTheAffectingStatementMethod() - { - $connection = $this->getMockConnection(['affectingStatement']); - $connection->expects($this->once())->method('affectingStatement')->with($this->equalTo('foo'), $this->equalTo( - ['bar'] - ))->willReturn( - 'baz' - ); - $results = $connection->delete('foo', ['bar']); - $this->assertEquals('baz', $results); - } - - - public function testStatementProperlyCallsPDO() - { - $pdo = $this->getMock(DatabaseConnectionTestMockPDO::class, ['prepare']); - $statement = $this->getMock('PDOStatement', ['execute']); - $statement->expects($this->once())->method('execute')->with($this->equalTo(['bar']))->willReturn(true); - $pdo->expects($this->once())->method('prepare')->with($this->equalTo('foo'))->willReturn($statement); - $mock = $this->getMockConnection(['prepareBindings'], $pdo); - $mock->expects($this->once())->method('prepareBindings')->with($this->equalTo(['bar']))->willReturn( - ['bar'] - ); - $results = $mock->statement('foo', ['bar']); - $this->assertEquals(true, $results); - $log = $mock->getQueryLog(); - $this->assertEquals('foo', $log[0]['query']); - $this->assertEquals(['bar'], $log[0]['bindings']); - $this->assertIsNumeric($log[0]['time']); - } - - - public function testAffectingStatementProperlyCallsPDO() - { - $pdo = $this->getMock(DatabaseConnectionTestMockPDO::class, ['prepare']); - $statement = $this->getMock('PDOStatement', ['execute', 'rowCount']); - $statement->expects($this->once())->method('execute')->with($this->equalTo(['foo' => 'bar'])); - $statement->expects($this->once())->method('rowCount')->willReturn(100); - $pdo->expects($this->once())->method('prepare')->with('foo')->willReturn($statement); - $mock = $this->getMockConnection(['prepareBindings'], $pdo); - $mock->expects($this->once())->method('prepareBindings')->with($this->equalTo(['foo' => 'bar']))->willReturn( - ['foo' => 'bar'] - ); - $results = $mock->update('foo', ['foo' => 'bar']); - $this->assertEquals(100, $results); - $log = $mock->getQueryLog(); - $this->assertEquals('foo', $log[0]['query']); - $this->assertEquals(['foo' => 'bar'], $log[0]['bindings']); - $this->assertIsNumeric($log[0]['time']); - } - - - public function testBeganTransactionFiresEventsIfSet() - { - $pdo = $this->createMock(DatabaseConnectionTestMockPDO::class); - $connection = $this->getMockConnection(['getName'], $pdo); - $connection->expects($this->any())->method('getName')->willReturn('name'); - $connection->setEventDispatcher($events = m::mock(Dispatcher::class)); - $events->shouldReceive('dispatch')->once()->with('connection.name.beganTransaction', $connection); - $connection->beginTransaction(); - } - - - public function testCommitedFiresEventsIfSet() - { - $pdo = $this->getMock(DatabaseConnectionTestMockPDO::class); - $connection = $this->getMockConnection(['getName'], $pdo); - $connection->expects($this->once())->method('getName')->willReturn('name'); - $connection->setEventDispatcher($events = m::mock(Dispatcher::class)); - $events->shouldReceive('dispatch')->once()->with('connection.name.committed', $connection); - $connection->commit(); - } - - - public function testRollBackedFiresEventsIfSet() - { - $pdo = $this->getMock(DatabaseConnectionTestMockPDO::class); - $connection = $this->getMockConnection(['getName'], $pdo); - $connection->expects($this->once())->method('getName')->willReturn('name'); - $connection->setEventDispatcher($events = m::mock(Dispatcher::class)); - $events->shouldReceive('dispatch')->once()->with('connection.name.rollingBack', $connection); - $connection->rollBack(); - } - - - public function testTransactionMethodRunsSuccessfully() - { - $pdo = $this->getMock(DatabaseConnectionTestMockPDO::class, ['beginTransaction', 'commit']); - $mock = $this->getMockConnection([], $pdo); - $pdo->expects($this->once())->method('beginTransaction'); - $pdo->expects($this->once())->method('commit'); - $result = $mock->transaction(function($db) { return $db; }); - $this->assertEquals($mock, $result); - } - - - public function testTransactionMethodRollsbackAndThrows() - { - $pdo = $this->getMock(DatabaseConnectionTestMockPDO::class, ['beginTransaction', 'commit', 'rollBack']); - $mock = $this->getMockConnection([], $pdo); - $pdo->expects($this->once())->method('beginTransaction'); - $pdo->expects($this->once())->method('rollBack'); - $pdo->expects($this->never())->method('commit'); - try - { - $mock->transaction(function(): never { throw new Exception('foo'); }); - } - catch (Exception $e) - { - $this->assertEquals('foo', $e->getMessage()); - } - } - - public function testTransactionMethodDisallowPDOChanging() - { - $this->expectException(RuntimeException::class); - $pdo = $this->getMock(DatabaseConnectionTestMockPDO::class, ['beginTransaction', 'commit', 'rollBack']); - $pdo->expects($this->once())->method('beginTransaction'); - $pdo->expects($this->once())->method('rollBack'); - $pdo->expects($this->never())->method('commit'); - - $mock = $this->getMockConnection([], $pdo); - - $mock->setReconnector( - function ($connection) { - $connection->setPDO(null); - } - ); - - $mock->transaction(function ($connection) { $connection->reconnect(); }); - } - - - public function testFromCreatesNewQueryBuilder() - { - $conn = $this->getMockConnection(); - $conn->setQueryGrammar(m::mock(Grammar::class)); - $conn->setPostProcessor(m::mock(Processor::class)); - $builder = $conn->table('users'); - $this->assertInstanceOf(\Illuminate\Database\Query\Builder::class, $builder); - $this->assertEquals('users', $builder->from); - } - - - public function testPrepareBindings() - { - $date = m::mock('DateTime'); - $date->shouldReceive('format')->once()->with('foo')->andReturn('bar'); - $bindings = ['test' => $date]; - $conn = $this->getMockConnection(); - $grammar = m::mock(Grammar::class); - $grammar->shouldReceive('getDateFormat')->once()->andReturn('foo'); - $conn->setQueryGrammar($grammar); - $result = $conn->prepareBindings($bindings); - $this->assertEquals(['test' => 'bar'], $result); - } - - - public function testLogQueryFiresEventsIfSet() - { - $connection = $this->getMockConnection(); - $connection->logQuery('foo', [], time()); - $connection->setEventDispatcher($events = m::mock(Dispatcher::class)); - $events->shouldReceive('dispatch')->once()->with('illuminate.query', ['foo', [], null, null]); - $connection->logQuery('foo', [], null); - } - - - public function testPretendOnlyLogsQueries() - { - $connection = $this->getMockConnection(); - $queries = $connection->pretend(function($connection) - { - $connection->select('foo bar', ['baz']); - }); - $this->assertEquals('foo bar', $queries[0]['query']); - $this->assertEquals(['baz'], $queries[0]['bindings']); - } - - - public function testSchemaBuilderCanBeCreated() - { - $connection = $this->getMockConnection(); - $schema = $connection->getSchemaBuilder(); - $this->assertInstanceOf(Builder::class, $schema); - $this->assertSame($connection, $schema->getConnection()); - } - - - public function testResolvingPaginatorThroughClosure() - { - $connection = $this->getMockConnection(); - $paginator = m::mock(Factory::class); - $connection->setPaginator(function() use ($paginator) - { - return $paginator; - }); - $this->assertEquals($paginator, $connection->getPaginator()); - } - - - public function testResolvingCacheThroughClosure() - { - $connection = $this->getMockConnection(); - $cache = m::mock(CacheManager::class); - $connection->setCacheManager(function() use ($cache) - { - return $cache; - }); - $this->assertEquals($cache, $connection->getCacheManager()); - } - - - protected function getMockConnection($methods = [], $pdo = null) - { - $pdo = $pdo ?: new DatabaseConnectionTestMockPDO; - $defaults = ['getDefaultQueryGrammar', 'getDefaultPostProcessor', 'getDefaultSchemaGrammar']; - - $connection = $this->getMockBuilder(Connection::class) - ->onlyMethods(array_merge($defaults, $methods)) - ->setConstructorArgs([$pdo]) - ->getMock(); - - $connection->enableQueryLog(); - - return $connection; - } - -} - -class DatabaseConnectionTestMockPDO extends PDO { - public function __construct() { - // - } -} diff --git a/tests/Database/DatabaseConnectorTest.php b/tests/Database/DatabaseConnectorTest.php deleted file mode 100755 index 83f3fb351..000000000 --- a/tests/Database/DatabaseConnectorTest.php +++ /dev/null @@ -1,185 +0,0 @@ -setDefaultOptions([0 => 'foo', 1 => 'bar']); - $this->assertEquals( - [0 => 'baz', 1 => 'bar', 2 => 'boom'], - $connector->getOptions(['options' => [0 => 'baz', 2 => 'boom']]) - ); - } - - - /** - * @dataProvider mySqlConnectProvider - */ - public function testMySqlConnectCallsCreateConnectionWithProperArguments($dsn, $config) - { - $connector = $this->getMock(MySqlConnector::class, ['createConnection', 'getOptions']); - $connection = m::mock('stdClass'); - $connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn( - ['options'] - ); - $connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo( - ['options'] - ))->willReturn( - $connection - ); - $connection->shouldReceive('prepare')->once()->with('set names \'utf8\' collate \'utf8_unicode_ci\'')->andReturn($connection); - $connection->shouldReceive('prepare')->once()->with('set session sql_mode=\'\'')->andReturn($connection); - $connection->shouldReceive('execute')->times(2); - $connection->shouldReceive('exec')->zeroOrMoreTimes(); - $result = $connector->connect($config); - - $this->assertSame($result, $connection); - } - - - public function mySqlConnectProvider() - { - return [ - ['mysql:host=foo;dbname=bar', ['host' => 'foo', 'database' => 'bar', 'collation' => 'utf8_unicode_ci', 'charset' => 'utf8']], - ['mysql:host=foo;port=111;dbname=bar', ['host' => 'foo', 'database' => 'bar', 'port' => 111, 'collation' => 'utf8_unicode_ci', 'charset' => 'utf8']], - ['mysql:unix_socket=baz;dbname=bar', ['host' => 'foo', 'database' => 'bar', 'port' => 111, 'unix_socket' => 'baz', 'collation' => 'utf8_unicode_ci', 'charset' => 'utf8']], - ]; - } - - - public function testPostgresConnectCallsCreateConnectionWithProperArguments() - { - $dsn = 'pgsql:host=foo;dbname=bar;port=111'; - $config = ['host' => 'foo', 'database' => 'bar', 'port' => 111, 'charset' => 'utf8']; - $connector = $this->getMock(PostgresConnector::class, ['createConnection', 'getOptions']); - $connection = m::mock('stdClass'); - $connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn( - ['options'] - ); - $connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo( - ['options'] - ))->willReturn( - $connection - ); - $connection->shouldReceive('prepare')->once()->with('set names \'utf8\'')->andReturn($connection); - $connection->shouldReceive('execute')->once(); - $result = $connector->connect($config); - - $this->assertSame($result, $connection); - } - - - public function testPostgresSearchPathIsSet() - { - $dsn = 'pgsql:host=foo;dbname=bar'; - $config = ['host' => 'foo', 'database' => 'bar', 'schema' => 'public', 'charset' => 'utf8']; - $connector = $this->getMock(PostgresConnector::class, ['createConnection', 'getOptions']); - $connection = m::mock('stdClass'); - $connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn( - ['options'] - ); - $connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo( - ['options'] - ))->willReturn( - $connection - ); - $connection->shouldReceive('prepare')->once()->with('set names \'utf8\'')->andReturn($connection); - $connection->shouldReceive('prepare')->once()->with("set search_path to public")->andReturn($connection); - $connection->shouldReceive('execute')->twice(); - $result = $connector->connect($config); - - $this->assertSame($result, $connection); - } - - - public function testSQLiteMemoryDatabasesMayBeConnectedTo() - { - $dsn = 'sqlite::memory:'; - $config = ['database' => ':memory:']; - $connector = $this->getMock(SQLiteConnector::class, ['createConnection', 'getOptions']); - $connection = m::mock('stdClass'); - $connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn( - ['options'] - ); - $connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo( - ['options'] - ))->willReturn( - $connection - ); - $result = $connector->connect($config); - - $this->assertSame($result, $connection); - } - - - public function testSQLiteFileDatabasesMayBeConnectedTo() - { - $dsn = 'sqlite:'.__DIR__; - $config = ['database' => __DIR__]; - $connector = $this->getMock(SQLiteConnector::class, ['createConnection', 'getOptions']); - $connection = m::mock('stdClass'); - $connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn( - ['options'] - ); - $connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo( - ['options'] - ))->willReturn( - $connection - ); - $result = $connector->connect($config); - - $this->assertSame($result, $connection); - } - - - public function testSqlServerConnectCallsCreateConnectionWithProperArguments() - { - $config = ['host' => 'foo', 'database' => 'bar', 'port' => 111]; - $dsn = $this->getDsn($config); - $connector = $this->getMock(SqlServerConnector::class, ['createConnection', 'getOptions']); - $connection = m::mock('stdClass'); - $connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn( - ['options'] - ); - $connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo( - ['options'] - ))->willReturn( - $connection - ); - $result = $connector->connect($config); - - $this->assertSame($result, $connection); - } - - protected function getDsn(array $config) - { - extract($config); - - if (in_array('dblib', PDO::getAvailableDrivers())) - { - $port = isset($config['port']) ? ':'.$port : ''; - return "dblib:host={$host}{$port};dbname={$database}"; - } - else - { - $port = isset($config['port']) ? ','.$port : ''; - return "sqlsrv:Server={$host}{$port};Database={$database}"; - } - } - -} diff --git a/tests/Database/DatabaseEloquentBelongsToManyTest.php b/tests/Database/DatabaseEloquentBelongsToManyTest.php deleted file mode 100755 index cd0183a91..000000000 --- a/tests/Database/DatabaseEloquentBelongsToManyTest.php +++ /dev/null @@ -1,506 +0,0 @@ -fill(['name' => 'taylor', 'pivot_user_id' => 1, 'pivot_role_id' => 2]); - $model2 = new EloquentBelongsToManyModelStub; - $model2->fill(['name' => 'dayle', 'pivot_user_id' => 3, 'pivot_role_id' => 4]); - $models = [$model1, $model2]; - - $baseBuilder = m::mock(\Illuminate\Database\Query\Builder::class); - - $relation = $this->getRelation(); - $relation->getParent()->shouldReceive('getConnectionName')->andReturn('foo.connection'); - $relation->getQuery()->shouldReceive('addSelect')->once()->with( - ['roles.*', 'user_role.user_id as pivot_user_id', 'user_role.role_id as pivot_role_id'] - )->andReturn($relation->getQuery()); - $relation->getQuery()->shouldReceive('getModels')->once()->andReturn($models); - $relation->getQuery()->shouldReceive('eagerLoadRelations')->once()->with($models)->andReturn($models); - $relation->getRelated()->shouldReceive('newCollection')->andReturnUsing(function($array) { return new Collection($array); }); - $relation->getQuery()->shouldReceive('getQuery')->once()->andReturn($baseBuilder); - $results = $relation->get(); - - $this->assertInstanceOf(Collection::class, $results); - - // Make sure the foreign keys were set on the pivot models... - $this->assertEquals('user_id', $results[0]->pivot->getForeignKey()); - $this->assertEquals('role_id', $results[0]->pivot->getOtherKey()); - - $this->assertEquals('taylor', $results[0]->name); - $this->assertEquals(1, $results[0]->pivot->user_id); - $this->assertEquals(2, $results[0]->pivot->role_id); - $this->assertEquals('foo.connection', $results[0]->pivot->getConnectionName()); - $this->assertEquals('dayle', $results[1]->name); - $this->assertEquals(3, $results[1]->pivot->user_id); - $this->assertEquals(4, $results[1]->pivot->role_id); - $this->assertEquals('foo.connection', $results[1]->pivot->getConnectionName()); - $this->assertEquals('user_role', $results[0]->pivot->getTable()); - $this->assertTrue($results[0]->pivot->exists); - } - - - public function testTimestampsCanBeRetrievedProperly() - { - $model1 = new EloquentBelongsToManyModelStub; - $model1->fill(['name' => 'taylor', 'pivot_user_id' => 1, 'pivot_role_id' => 2]); - $model2 = new EloquentBelongsToManyModelStub; - $model2->fill(['name' => 'dayle', 'pivot_user_id' => 3, 'pivot_role_id' => 4]); - $models = [$model1, $model2]; - - $baseBuilder = m::mock(\Illuminate\Database\Query\Builder::class); - - $relation = $this->getRelation()->withTimestamps(); - $relation->getParent()->shouldReceive('getConnectionName')->andReturn('foo.connection'); - $relation->getQuery()->shouldReceive('addSelect')->once()->with([ - 'roles.*', - 'user_role.user_id as pivot_user_id', - 'user_role.role_id as pivot_role_id', - 'user_role.created_at as pivot_created_at', - 'user_role.updated_at as pivot_updated_at', - ])->andReturn($relation->getQuery()); - $relation->getQuery()->shouldReceive('getModels')->once()->andReturn($models); - $relation->getQuery()->shouldReceive('eagerLoadRelations')->once()->with($models)->andReturn($models); - $relation->getRelated()->shouldReceive('newCollection')->andReturnUsing(function($array) { return new Collection($array); }); - $relation->getQuery()->shouldReceive('getQuery')->once()->andReturn($baseBuilder); - $results = $relation->get(); - } - - - public function testModelsAreProperlyMatchedToParents() - { - $relation = $this->getRelation(); - - $result1 = new EloquentBelongsToManyModelPivotStub; - $result1->pivot->user_id = 1; - $result2 = new EloquentBelongsToManyModelPivotStub; - $result2->pivot->user_id = 2; - $result3 = new EloquentBelongsToManyModelPivotStub; - $result3->pivot->user_id = 2; - - $model1 = new EloquentBelongsToManyModelStub; - $model1->id = 1; - $model2 = new EloquentBelongsToManyModelStub; - $model2->id = 2; - $model3 = new EloquentBelongsToManyModelStub; - $model3->id = 3; - - $relation->getRelated()->shouldReceive('newCollection')->andReturnUsing(function($array) { return new Collection($array); }); - $models = $relation->match([$model1, $model2, $model3], new Collection([$result1, $result2, $result3]), 'foo'); - - $this->assertEquals(1, $models[0]->foo[0]->pivot->user_id); - $this->assertCount(1, $models[0]->foo); - - $this->assertEquals(2, $models[1]->foo[0]->pivot->user_id); - $this->assertEquals(2, $models[1]->foo[1]->pivot->user_id); - $this->assertCount(2, $models[1]->foo); - $this->assertEmpty($models[2]->foo); - } - - - public function testRelationIsProperlyInitialized() - { - $relation = $this->getRelation(); - $relation->getRelated()->shouldReceive('newCollection')->andReturnUsing(function($array = []) { return new Collection($array); }); - $model = m::mock(Model::class); - $model->shouldReceive('setRelation')->once()->with('foo', m::type(Collection::class)); - $models = $relation->initRelation([$model], 'foo'); - - $this->assertEquals([$model], $models); - } - - - public function testEagerConstraintsAreProperlyAdded() - { - $relation = $this->getRelation(); - $relation->getQuery()->shouldReceive('whereIn')->once()->with('user_role.user_id', [1, 2]); - $model1 = new EloquentBelongsToManyModelStub; - $model1->id = 1; - $model2 = new EloquentBelongsToManyModelStub; - $model2->id = 2; - $relation->addEagerConstraints([$model1, $model2]); - } - - - public function testAttachInsertsPivotTableRecord() - { - $relation = $this->getMock(BelongsToMany::class, ['touchIfTouching'], $this->getRelationArguments()); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('user_role')->andReturn($query); - $query->shouldReceive('insert')->once()->with([['user_id' => 1, 'role_id' => 2, 'foo' => 'bar']])->andReturn(true); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $relation->expects($this->once())->method('touchIfTouching'); - - $relation->attach(2, ['foo' => 'bar']); - } - - - public function testAttachMultipleInsertsPivotTableRecord() - { - $relation = $this->getMock(BelongsToMany::class, ['touchIfTouching'], $this->getRelationArguments()); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('user_role')->andReturn($query); - $query->shouldReceive('insert')->once()->with( - [ - ['user_id' => 1, 'role_id' => 2, 'foo' => 'bar'], - ['user_id' => 1, 'role_id' => 3, 'baz' => 'boom', 'foo' => 'bar'], - ] - )->andReturn(true); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $relation->expects($this->once())->method('touchIfTouching'); - - $relation->attach([2, 3 => ['baz' => 'boom']], ['foo' => 'bar']); - } - - - public function testAttachInsertsPivotTableRecordWithTimestampsWhenNecessary() - { - $relation = $this->getMock(BelongsToMany::class, ['touchIfTouching'], $this->getRelationArguments()); - $relation->withTimestamps(); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('user_role')->andReturn($query); - $carbon = new Carbon; - $query->shouldReceive('insert')->once()->with( - [['user_id' => 1, 'role_id' => 2, 'foo' => 'bar', 'created_at' => $carbon, 'updated_at' => $carbon]] - )->andReturn(true); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $relation->getParent()->shouldReceive('freshTimestamp')->once()->andReturn($carbon); - $relation->expects($this->once())->method('touchIfTouching'); - - $relation->attach(2, ['foo' => 'bar']); - } - - - public function testAttachInsertsPivotTableRecordWithACreatedAtTimestamp() - { - $relation = $this->getMock(BelongsToMany::class, ['touchIfTouching'], $this->getRelationArguments()); - $relation->withPivot('created_at'); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('user_role')->andReturn($query); - $carbon = new Carbon; - $query->shouldReceive('insert')->once()->with( - [['user_id' => 1, 'role_id' => 2, 'foo' => 'bar', 'created_at' => $carbon]] - )->andReturn(true); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $relation->getParent()->shouldReceive('freshTimestamp')->once()->andReturn($carbon); - $relation->expects($this->once())->method('touchIfTouching'); - - $relation->attach(2, ['foo' => 'bar']); - } - - - public function testAttachInsertsPivotTableRecordWithAnUpdatedAtTimestamp() - { - $relation = $this->getMock(BelongsToMany::class, ['touchIfTouching'], $this->getRelationArguments()); - $relation->withPivot('updated_at'); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('user_role')->andReturn($query); - $carbon = new Carbon; - $query->shouldReceive('insert')->once()->with( - [['user_id' => 1, 'role_id' => 2, 'foo' => 'bar', 'updated_at' => $carbon]] - )->andReturn(true); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $relation->getParent()->shouldReceive('freshTimestamp')->once()->andReturn($carbon); - $relation->expects($this->once())->method('touchIfTouching'); - - $relation->attach(2, ['foo' => 'bar']); - } - - - public function testDetachRemovesPivotTableRecord() - { - $relation = $this->getMock(BelongsToMany::class, ['touchIfTouching'], $this->getRelationArguments()); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('user_role')->andReturn($query); - $query->shouldReceive('where')->once()->with('user_id', 1)->andReturn($query); - $query->shouldReceive('whereIn')->once()->with('role_id', [1, 2, 3]); - $query->shouldReceive('delete')->once()->andReturn(true); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $relation->expects($this->once())->method('touchIfTouching'); - - $this->assertTrue($relation->detach([1, 2, 3])); - } - - - public function testDetachWithSingleIDRemovesPivotTableRecord() - { - $relation = $this->getMock(BelongsToMany::class, ['touchIfTouching'], $this->getRelationArguments()); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('user_role')->andReturn($query); - $query->shouldReceive('where')->once()->with('user_id', 1)->andReturn($query); - $query->shouldReceive('whereIn')->once()->with('role_id', [1]); - $query->shouldReceive('delete')->once()->andReturn(true); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $relation->expects($this->once())->method('touchIfTouching'); - - $this->assertTrue($relation->detach([1])); - } - - - public function testDetachMethodClearsAllPivotRecordsWhenNoIDsAreGiven() - { - $relation = $this->getMock(BelongsToMany::class, ['touchIfTouching'], $this->getRelationArguments()); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('user_role')->andReturn($query); - $query->shouldReceive('where')->once()->with('user_id', 1)->andReturn($query); - $query->shouldReceive('whereIn')->never(); - $query->shouldReceive('delete')->once()->andReturn(true); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $relation->expects($this->once())->method('touchIfTouching'); - - $this->assertTrue($relation->detach()); - } - - - public function testCreateMethodCreatesNewModelAndInsertsAttachmentRecord() - { - $relation = $this->getMock(BelongsToMany::class, ['attach'], $this->getRelationArguments()); - $relation->getRelated()->shouldReceive('newInstance')->once()->andReturn($model = m::mock(Model::class))->with( - ['attributes'] - ); - $model->shouldReceive('save')->once(); - $model->shouldReceive('getKey')->andReturn('foo'); - $relation->expects($this->once())->method('attach')->with('foo', ['joining']); - - $this->assertEquals($model, $relation->create(['attributes'], ['joining'])); - } - - - /** - * @dataProvider syncMethodListProvider - */ - public function testSyncMethodSyncsIntermediateTableWithGivenArray($list) - { - $relation = $this->getMock(BelongsToMany::class, ['attach', 'detach'], $this->getRelationArguments()); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('user_role')->andReturn($query); - $query->shouldReceive('where')->once()->with('user_id', 1)->andReturn($query); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $query->shouldReceive('pluck')->once()->with('role_id')->andReturn([1, 2, 3]); - $relation->expects($this->once())->method('attach')->with($this->equalTo(4), $this->equalTo([]), $this->equalTo(false)); - $relation->expects($this->once())->method('detach')->with($this->equalTo([1])); - $relation->getRelated()->shouldReceive('touches')->andReturn(false); - $relation->getParent()->shouldReceive('touches')->andReturn(false); - - $this->assertEquals(['attached' => [4], 'detached' => [1], 'updated' => []], $relation->sync($list)); - } - - - public function syncMethodListProvider() - { - return [ - [[2, 3, 4]], - [['2', '3', '4']], - ]; - } - - - public function testSyncMethodSyncsIntermediateTableWithGivenArrayAndAttributes() - { - $relation = $this->getMock(BelongsToMany::class, ['attach', 'detach', 'touchIfTouching', 'updateExistingPivot'], $this->getRelationArguments()); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('user_role')->andReturn($query); - $query->shouldReceive('where')->once()->with('user_id', 1)->andReturn($query); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $query->shouldReceive('pluck')->once()->with('role_id')->andReturn([1, 2, 3]); - $relation->expects($this->once())->method('attach')->with($this->equalTo(4), $this->equalTo(['foo' => 'bar']), $this->equalTo(false)); - $relation->expects($this->once())->method('updateExistingPivot')->with($this->equalTo(3), $this->equalTo( - ['baz' => 'qux'] - ), $this->equalTo(false))->willReturn( - true - ); - $relation->expects($this->once())->method('detach')->with($this->equalTo([1])); - $relation->expects($this->once())->method('touchIfTouching'); - - $this->assertEquals( - ['attached' => [4], 'detached' => [1], 'updated' => [3]], $relation->sync( - [2, 3 => ['baz' => 'qux'], 4 => ['foo' => 'bar']] - )); - } - - - public function testSyncMethodDoesntReturnValuesThatWereNotUpdated() - { - $relation = $this->getMock(BelongsToMany::class, ['attach', 'detach', 'touchIfTouching', 'updateExistingPivot'], $this->getRelationArguments()); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('user_role')->andReturn($query); - $query->shouldReceive('where')->once()->with('user_id', 1)->andReturn($query); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $query->shouldReceive('pluck')->once()->with('role_id')->andReturn([1, 2, 3]); - $relation->expects($this->once())->method('attach')->with($this->equalTo(4), $this->equalTo(['foo' => 'bar']), $this->equalTo(false)); - $relation->expects($this->once())->method('updateExistingPivot')->with($this->equalTo(3), $this->equalTo( - ['baz' => 'qux'] - ), $this->equalTo(false))->willReturn( - false - ); - $relation->expects($this->once())->method('detach')->with($this->equalTo([1])); - $relation->expects($this->once())->method('touchIfTouching'); - - $this->assertEquals( - ['attached' => [4], 'detached' => [1], 'updated' => []], $relation->sync( - [2, 3 => ['baz' => 'qux'], 4 => ['foo' => 'bar']] - )); - } - - - public function testTouchMethodSyncsTimestamps() - { - $relation = $this->getRelation(); - $relation->getRelated()->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at'); - $carbon = new Carbon; - $relation->getRelated()->shouldReceive('freshTimestamp')->andReturn($carbon); - $relation->getRelated()->shouldReceive('getQualifiedKeyName')->andReturn('table.id'); - $relation->getQuery()->shouldReceive('select')->once()->with('table.id')->andReturn($relation->getQuery()); - $relation->getQuery()->shouldReceive('pluck')->once()->with('id')->andReturn([1, 2, 3]); - $relation->getRelated()->shouldReceive('newQuery')->once()->andReturn($query = m::mock(Builder::class)); - $query->shouldReceive('whereIn')->once()->with('id', [1, 2, 3])->andReturn($query); - $query->shouldReceive('update')->once()->with(['updated_at' => $carbon]); - - $relation->touch(); - } - - - public function testTouchIfTouching() - { - $relation = $this->getMock(BelongsToMany::class, ['touch', 'touchingParent'], $this->getRelationArguments()); - $relation->expects($this->once())->method('touchingParent')->willReturn(true); - $relation->getParent()->shouldReceive('touch')->once(); - $relation->getParent()->shouldReceive('touches')->once()->with('relation_name')->andReturn(true); - $relation->expects($this->once())->method('touch'); - - $relation->touchIfTouching(); - } - - - public function testSyncMethodConvertsCollectionToArrayOfKeys() - { - $relation = $this->getMock(BelongsToMany::class, ['attach', 'detach', 'touchIfTouching', 'formatSyncList'], $this->getRelationArguments()); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('user_role')->andReturn($query); - $query->shouldReceive('where')->once()->with('user_id', 1)->andReturn($query); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $query->shouldReceive('pluck')->once()->with('role_id')->andReturn([1, 2, 3]); - - $collection = m::mock(Collection::class); - $collection->shouldReceive('modelKeys')->once()->andReturn([1, 2, 3]); - $relation->expects($this->once())->method('formatSyncList')->with([1, 2, 3])->willReturn( - [1 => [], 2 => [], 3 => []] - ); - $relation->sync($collection); - } - - - public function testWherePivotParamsUsedForNewQueries() - { - $relation = $this->getMock(BelongsToMany::class, ['attach', 'detach', 'touchIfTouching', 'formatSyncList'], $this->getRelationArguments()); - - // we expect to call $relation->wherePivot() - $relation->getQuery()->shouldReceive('where')->once()->andReturn($relation); - - // Our sync() call will produce a new query - $mockQueryBuilder = m::mock('stdClass'); - $query = m::mock('stdClass'); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - - // BelongsToMany::newPivotStatement() sets this - $query->shouldReceive('from')->once()->with('user_role')->andReturn($query); - - // BelongsToMany::newPivotQuery() sets this - $query->shouldReceive('where')->once()->with('user_id', 1)->andReturn($query); - - // This is our test! The wherePivot() params also need to be called - $query->shouldReceive('where')->once()->with('foo', '=', 'bar')->andReturn($query); - - // This is so $relation->sync() works - $query->shouldReceive('pluck')->once()->with('role_id')->andReturn([1, 2, 3]); - $relation->expects($this->once())->method('formatSyncList')->with([1, 2, 3])->willReturn( - [1 => [], 2 => [], 3 => []] - ); - - - $relation = $relation->wherePivot('foo', '=', 'bar'); // these params are to be stored - $relation->sync([1,2,3]); // triggers the whole process above - } - - - public function getRelation() - { - [$builder, $parent] = $this->getRelationArguments(); - - return new BelongsToMany($builder, $parent, 'user_role', 'user_id', 'role_id', 'relation_name'); - } - - - public function getRelationArguments() - { - $parent = m::mock(Model::class); - $parent->shouldReceive('getKey')->andReturn(1); - $parent->shouldReceive('getCreatedAtColumn')->andReturn('created_at'); - $parent->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at'); - - $builder = m::mock(Builder::class); - $related = m::mock(Model::class); - $builder->shouldReceive('getModel')->andReturn($related); - - $related->shouldReceive('getTable')->andReturn('roles'); - $related->shouldReceive('getKeyName')->andReturn('id'); - $related->shouldReceive('newPivot')->andReturnUsing(function() - { - $reflector = new ReflectionClass(Pivot::class); - return $reflector->newInstanceArgs(func_get_args()); - }); - - $builder->shouldReceive('join')->once()->with('user_role', 'roles.id', '=', 'user_role.role_id'); - $builder->shouldReceive('where')->once()->with('user_role.user_id', '=', 1); - - return [$builder, $parent, 'user_role', 'user_id', 'role_id', 'relation_name']; - } - -} - -class EloquentBelongsToManyModelStub extends Illuminate\Database\Eloquent\Model { - protected array $guarded = []; -} - -class EloquentBelongsToManyModelPivotStub extends Illuminate\Database\Eloquent\Model { - public $pivot; - public function __construct() - { - $this->pivot = new EloquentBelongsToManyPivotStub; - } -} - -class EloquentBelongsToManyPivotStub { - public $user_id; -} diff --git a/tests/Database/DatabaseEloquentBelongsToTest.php b/tests/Database/DatabaseEloquentBelongsToTest.php deleted file mode 100755 index 43eef7b42..000000000 --- a/tests/Database/DatabaseEloquentBelongsToTest.php +++ /dev/null @@ -1,108 +0,0 @@ -getRelation(); - $mock = m::mock(Model::class); - $mock->shouldReceive('fill')->once()->with(['attributes'])->andReturn($mock); - $mock->shouldReceive('save')->once()->andReturn(true); - $relation->getQuery()->shouldReceive('first')->once()->andReturn($mock); - - $this->assertTrue($relation->update(['attributes'])); - } - - - public function testEagerConstraintsAreProperlyAdded() - { - $relation = $this->getRelation(); - $relation->getQuery()->shouldReceive('whereIn')->once()->with('relation.id', ['foreign.value', 'foreign.value.two'] - ); - $models = [new EloquentBelongsToModelStub, new EloquentBelongsToModelStub, new AnotherEloquentBelongsToModelStub]; - $relation->addEagerConstraints($models); - } - - - public function testRelationIsProperlyInitialized() - { - $relation = $this->getRelation(); - $model = m::mock(Model::class); - $model->shouldReceive('setRelation')->once()->with('foo', null); - $models = $relation->initRelation([$model], 'foo'); - - $this->assertEquals([$model], $models); - } - - - public function testModelsAreProperlyMatchedToParents() - { - $relation = $this->getRelation(); - $result1 = m::mock('stdClass'); - $result1->shouldReceive('getAttribute')->with('id')->andReturn(1); - $result2 = m::mock('stdClass'); - $result2->shouldReceive('getAttribute')->with('id')->andReturn(2); - $model1 = new EloquentBelongsToModelStub; - $model1->foreign_key = 1; - $model2 = new EloquentBelongsToModelStub; - $model2->foreign_key = 2; - $models = $relation->match([$model1, $model2], new Collection([$result1, $result2]), 'foo'); - - $this->assertEquals(1, $models[0]->foo->getAttribute('id')); - $this->assertEquals(2, $models[1]->foo->getAttribute('id')); - } - - - public function testAssociateMethodSetsForeignKeyOnModel() - { - $parent = m::mock(Model::class); - $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn('foreign.value'); - $relation = $this->getRelation($parent); - $associate = m::mock(Model::class); - $associate->shouldReceive('getAttribute')->once()->with('id')->andReturn(1); - $parent->shouldReceive('setAttribute')->once()->with('foreign_key', 1); - $parent->shouldReceive('setRelation')->once()->with('relation', $associate); - - $relation->associate($associate); - } - - - protected function getRelation($parent = null) - { - $builder = m::mock(Builder::class); - $builder->shouldReceive('where')->with('relation.id', '=', 'foreign.value'); - $related = m::mock(Model::class); - $related->shouldReceive('getKeyName')->andReturn('id'); - $related->shouldReceive('getTable')->andReturn('relation'); - $builder->shouldReceive('getModel')->andReturn($related); - $parent = $parent ?: new EloquentBelongsToModelStub; - return new BelongsTo($builder, $parent, 'foreign_key', 'id', 'relation'); - } - -} - -class EloquentBelongsToModelStub extends Illuminate\Database\Eloquent\Model { - - public $foreign_key = 'foreign.value'; - -} - -class AnotherEloquentBelongsToModelStub extends Illuminate\Database\Eloquent\Model { - - public $foreign_key = 'foreign.value.two'; - -} diff --git a/tests/Database/DatabaseEloquentBuilderTest.php b/tests/Database/DatabaseEloquentBuilderTest.php deleted file mode 100755 index 1dfec3f21..000000000 --- a/tests/Database/DatabaseEloquentBuilderTest.php +++ /dev/null @@ -1,629 +0,0 @@ -getMockQueryBuilder()]); - $builder->setModel($this->getMockModel()); - $builder->getQuery()->shouldReceive('where')->once()->with('foo_table.foo', '=', 'bar'); - $builder->shouldReceive('first')->with(['column'])->andReturn('baz'); - - $result = $builder->find('bar', ['column']); - $this->assertEquals('baz', $result); - } - - - public function testFindOrNewMethodModelFound() - { - $model = $this->getMockModel(); - $model->shouldReceive('findOrNew')->once()->andReturn('baz'); - - $builder = m::mock('Illuminate\Database\Eloquent\Builder[first]', [$this->getMockQueryBuilder()]); - $builder->setModel($model); - $builder->getQuery()->shouldReceive('where')->once()->with('foo_table.foo', '=', 'bar'); - $builder->shouldReceive('first')->with(['column'])->andReturn('baz'); - - $expected = $model->findOrNew('bar', ['column']); - $result = $builder->find('bar', ['column']); - $this->assertEquals($expected, $result); - } - - - public function testFindOrNewMethodModelNotFound() - { - $model = $this->getMockModel(); - $model->shouldReceive('findOrNew')->once()->andReturn(m::mock(Model::class)); - - $builder = m::mock('Illuminate\Database\Eloquent\Builder[first]', [$this->getMockQueryBuilder()]); - $builder->setModel($model); - $builder->getQuery()->shouldReceive('where')->once()->with('foo_table.foo', '=', 'bar'); - $builder->shouldReceive('first')->with(['column'])->andReturn(null); - - $result = $model->findOrNew('bar', ['column']); - $findResult = $builder->find('bar', ['column']); - $this->assertNull($findResult); - $this->assertInstanceOf(Model::class, $result); - } - - public function testFindOrFailMethodThrowsModelNotFoundException() - { - $this->expectException(Illuminate\Database\Eloquent\ModelNotFoundException::class); - $builder = m::mock('Illuminate\Database\Eloquent\Builder[first]', [$this->getMockQueryBuilder()]); - $builder->setModel($this->getMockModel()); - $builder->getQuery()->shouldReceive('where')->once()->with('foo_table.foo', '=', 'bar'); - $builder->shouldReceive('first')->with(['column'])->andReturn(null); - $result = $builder->findOrFail('bar', ['column']); - } - - public function testFirstOrFailMethodThrowsModelNotFoundException() - { - $this->expectException(Illuminate\Database\Eloquent\ModelNotFoundException::class); - $builder = m::mock('Illuminate\Database\Eloquent\Builder[first]', [$this->getMockQueryBuilder()]); - $builder->setModel($this->getMockModel()); - $builder->shouldReceive('first')->with(['column'])->andReturn(null); - $result = $builder->firstOrFail(['column']); - } - - - public function testFindWithMany() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder[get]', [$this->getMockQueryBuilder()]); - $builder->getQuery()->shouldReceive('whereIn')->once()->with('foo_table.foo', [1, 2]); - $builder->setModel($this->getMockModel()); - $builder->shouldReceive('get')->with(['column'])->andReturn('baz'); - - $result = $builder->find([1, 2], ['column']); - $this->assertEquals('baz', $result); - } - - - public function testFirstMethod() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder[get,take]', [$this->getMockQueryBuilder()]); - $builder->shouldReceive('take')->with(1)->andReturn($builder); - $builder->shouldReceive('get')->with(['*'])->andReturn(new Collection(['bar'])); - - $result = $builder->first(); - $this->assertEquals('bar', $result); - } - - - public function testGetMethodLoadsModelsAndHydratesEagerRelations() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder[getModels,eagerLoadRelations]', [$this->getMockQueryBuilder()] - ); - $builder->shouldReceive('getModels')->with(['foo'])->andReturn(['bar']); - $builder->shouldReceive('eagerLoadRelations')->with(['bar'])->andReturn(['bar', 'baz']); - $builder->setModel($this->getMockModel()); - $builder->getModel()->shouldReceive('newCollection')->with(['bar', 'baz'])->andReturn(new Collection( - ['bar', 'baz'] - )); - - $results = $builder->get(['foo']); - $this->assertEquals(['bar', 'baz'], $results->all()); - } - - - public function testGetMethodDoesntHydrateEagerRelationsWhenNoResultsAreReturned() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder[getModels,eagerLoadRelations]', [$this->getMockQueryBuilder()] - ); - $builder->shouldReceive('getModels')->with(['foo'])->andReturn([]); - $builder->shouldReceive('eagerLoadRelations')->never(); - $builder->setModel($this->getMockModel()); - $builder->getModel()->shouldReceive('newCollection')->with([])->andReturn(new Collection([])); - - $results = $builder->get(['foo']); - $this->assertEquals([], $results->all()); - } - - -public function testValueMethodWithModelFound() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder[first]', [$this->getMockQueryBuilder()]); - $mockModel = new StdClass; - $mockModel->name = 'foo'; - $builder->shouldReceive('first')->with(['name'])->andReturn($mockModel); - - $this->assertEquals('foo', $builder->value('name')); - } - - - public function testValueMethodWithModelNotFound() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder[first]', [$this->getMockQueryBuilder()]); - $builder->shouldReceive('first')->with(['name'])->andReturn(null); - - $this->assertNull($builder->value('name')); - } - - - public function testChunkExecuteCallbackOverPaginatedRequest() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder[forPage,get]', [$this->getMockQueryBuilder()]); - $builder->shouldReceive('forPage')->once()->with(1, 2)->andReturn($builder); - $builder->shouldReceive('forPage')->once()->with(2, 2)->andReturn($builder); - $builder->shouldReceive('forPage')->once()->with(3, 2)->andReturn($builder); - $builder->shouldReceive('get')->times(3)->andReturn(['foo1', 'foo2'], ['foo3'], []); - - $callbackExecutionAssertor = m::mock('StdClass'); - $callbackExecutionAssertor->shouldReceive('doSomething')->with('foo1')->once(); - $callbackExecutionAssertor->shouldReceive('doSomething')->with('foo2')->once(); - $callbackExecutionAssertor->shouldReceive('doSomething')->with('foo3')->once(); - - $builder->chunk(2, function($results) use($callbackExecutionAssertor) { - foreach ($results as $result) { - $callbackExecutionAssertor->doSomething($result); - } - }); - } - - - public function testListsReturnsTheMutatedAttributesOfAModel() - { - $builder = $this->getBuilder(); - $builder->getQuery()->shouldReceive('pluck')->with('name', '')->andReturn(['bar', 'baz']); - $builder->setModel($this->getMockModel()); - $builder->getModel()->shouldReceive('hasGetMutator')->with('name')->andReturn(true); - $builder->getModel()->shouldReceive('newFromBuilder')->with(['name' => 'bar'])->andReturn(new EloquentBuilderTestListsStub( - ['name' => 'bar'] - )); - $builder->getModel()->shouldReceive('newFromBuilder')->with(['name' => 'baz'])->andReturn(new EloquentBuilderTestListsStub( - ['name' => 'baz'] - )); - - $this->assertEquals(['foo_bar', 'foo_baz'], $builder->pluck('name')); - } - - - public function testListsWithoutModelGetterJustReturnTheAttributesFoundInDatabase() - { - $builder = $this->getBuilder(); - $builder->getQuery()->shouldReceive('pluck')->with('name', '')->andReturn(['bar', 'baz']); - $builder->setModel($this->getMockModel()); - $builder->getModel()->shouldReceive('hasGetMutator')->with('name')->andReturn(false); - - $this->assertEquals(['bar', 'baz'], $builder->pluck('name')); - } - - - public function testMacrosAreCalledOnBuilder() - { - unset($_SERVER['__test.builder']); - $builder = new Illuminate\Database\Eloquent\Builder(new Illuminate\Database\Query\Builder( - m::mock(ConnectionInterface::class), - m::mock(Grammar::class), - m::mock(Processor::class) - )); - $builder->macro('fooBar', function($builder) - { - $_SERVER['__test.builder'] = $builder; - - return $builder; - }); - $result = $builder->fooBar(); - - $this->assertEquals($builder, $result); - $this->assertEquals($builder, $_SERVER['__test.builder']); - unset($_SERVER['__test.builder']); - } - - - public function testPaginateMethod() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder[get]', [$this->getMockQueryBuilder()]); - $builder->setModel($this->getMockModel()); - $builder->getModel()->shouldReceive('getPerPage')->once()->andReturn(15); - $builder->getQuery()->shouldReceive('getPaginationCount')->once()->andReturn(10); - $conn = m::mock('stdClass'); - $paginator = m::mock('stdClass'); - $paginator->shouldReceive('getCurrentPage')->once()->andReturn(1); - $conn->shouldReceive('getPaginator')->once()->andReturn($paginator); - $builder->getQuery()->shouldReceive('getConnection')->once()->andReturn($conn); - $builder->getQuery()->shouldReceive('forPage')->once()->with(1, 15); - $builder->shouldReceive('get')->with(['*'])->andReturn(new Collection(['results'])); - $paginator->shouldReceive('make')->once()->with(['results'], 10, 15)->andReturn(['results']); - - $this->assertEquals(['results'], $builder->paginate()); - } - - - public function testPaginateMethodWithGroupedQuery() - { - $query = $this->getMock(\Illuminate\Database\Query\Builder::class, ['from', 'getConnection'], [ - m::mock(ConnectionInterface::class), - m::mock(Grammar::class), - m::mock(Processor::class), - ]); - $query->expects($this->once())->method('from')->willReturn('foo_table'); - $builder = $this->getMock(Builder::class, ['get'], [$query]); - $builder->setModel($this->getMockModel()); - $builder->getModel()->shouldReceive('getPerPage')->once()->andReturn(2); - $conn = m::mock('stdClass'); - $paginator = m::mock('stdClass'); - $paginator->shouldReceive('getCurrentPage')->once()->andReturn(2); - $conn->shouldReceive('getPaginator')->once()->andReturn($paginator); - $query->expects($this->once())->method('getConnection')->willReturn($conn); - $builder->expects($this->once())->method('get')->with($this->equalTo(['*']))->willReturn( - new Collection(['foo', 'bar', 'baz']) - ); - $paginator->shouldReceive('make')->once()->with(['baz'], 3, 2)->andReturn(['results']); - - $this->assertEquals(['results'], $builder->groupBy('foo')->paginate()); - } - - - public function testQuickPaginateMethod() - { - $query = $this->getMock(\Illuminate\Database\Query\Builder::class, ['from', 'getConnection', 'skip', 'take'], [ - m::mock(ConnectionInterface::class), - m::mock(Grammar::class), - m::mock(Processor::class), - ]); - $query->expects($this->once())->method('from')->willReturn('foo_table'); - $builder = $this->getMock(Builder::class, ['get'], [$query]); - $builder->setModel($this->getMockModel()); - $builder->getModel()->shouldReceive('getPerPage')->once()->andReturn(15); - $conn = m::mock('stdClass'); - $paginator = m::mock('stdClass'); - $paginator->shouldReceive('getCurrentPage')->once()->andReturn(1); - $conn->shouldReceive('getPaginator')->once()->andReturn($paginator); - $query->expects($this->once())->method('getConnection')->willReturn($conn); - $query->expects($this->once())->method('skip')->with(0)->willReturn($query); - $query->expects($this->once())->method('take')->with(16)->willReturn($query); - $builder->expects($this->once())->method('get')->with($this->equalTo(['*']))->willReturn( - new Collection(['results']) - ); - $paginator->shouldReceive('make')->once()->with(['results'], 15)->andReturn(['results']); - - $this->assertEquals(['results'], $builder->simplePaginate()); - } - - - public function testGetModelsProperlyHydratesModels() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder[get]', [$this->getMockQueryBuilder()]); - $records[] = ['name' => 'taylor', 'age' => 26]; - $records[] = ['name' => 'dayle', 'age' => 28]; - $builder->getQuery()->shouldReceive('get')->once()->with(['foo'])->andReturn($records); - $model = m::mock('Illuminate\Database\Eloquent\Model[getTable,getConnectionName,newInstance]'); - $model->shouldReceive('getTable')->once()->andReturn('foo_table'); - $builder->setModel($model); - $model->shouldReceive('getConnectionName')->once()->andReturn('foo_connection'); - $model->shouldReceive('newInstance')->andReturnUsing(function() { return new EloquentBuilderTestModelStub; }); - $models = $builder->getModels(['foo']); - - $this->assertEquals('taylor', $models[0]->name); - $this->assertEquals($models[0]->getAttributes(), $models[0]->getOriginal()); - $this->assertEquals('dayle', $models[1]->name); - $this->assertEquals($models[1]->getAttributes(), $models[1]->getOriginal()); - $this->assertEquals('foo_connection', $models[0]->getConnectionName()); - $this->assertEquals('foo_connection', $models[1]->getConnectionName()); - } - - - public function testEagerLoadRelationsLoadTopLevelRelationships() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder[loadRelation]', [$this->getMockQueryBuilder()]); - $nop1 = function() {}; - $nop2 = function() {}; - $builder->setEagerLoads(['foo' => $nop1, 'foo.bar' => $nop2]); - $builder->shouldAllowMockingProtectedMethods()->shouldReceive('loadRelation')->with(['models'], 'foo', $nop1)->andReturn( - ['foo'] - ); - - $results = $builder->eagerLoadRelations(['models']); - $this->assertEquals(['foo'], $results); - } - - - public function testRelationshipEagerLoadProcess() - { - $builder = m::mock('Illuminate\Database\Eloquent\Builder[getRelation]', [$this->getMockQueryBuilder()]); - $builder->setEagerLoads(['orders' => function($query) { $_SERVER['__eloquent.constrain'] = $query; }]); - $relation = m::mock('stdClass'); - $relation->shouldReceive('addEagerConstraints')->once()->with(['models']); - $relation->shouldReceive('initRelation')->once()->with(['models'], 'orders')->andReturn(['models']); - $relation->shouldReceive('getEager')->once()->andReturn(['results']); - $relation->shouldReceive('match')->once()->with(['models'], ['results'], 'orders')->andReturn(['models.matched'] - ); - $builder->shouldReceive('getRelation')->once()->with('orders')->andReturn($relation); - $results = $builder->eagerLoadRelations(['models']); - - $this->assertEquals(['models.matched'], $results); - $this->assertEquals($relation, $_SERVER['__eloquent.constrain']); - unset($_SERVER['__eloquent.constrain']); - } - - - public function testGetRelationProperlySetsNestedRelationships() - { - $builder = $this->getBuilder(); - $builder->setModel($this->getMockModel()); - $builder->getModel()->shouldReceive('orders')->once()->andReturn($relation = m::mock('stdClass')); - $relationQuery = m::mock('stdClass'); - $relation->shouldReceive('getQuery')->andReturn($relationQuery); - $relationQuery->shouldReceive('with')->once()->with(['lines' => null, 'lines.details' => null]); - $builder->setEagerLoads(['orders' => null, 'orders.lines' => null, 'orders.lines.details' => null]); - - $relation = $builder->getRelation('orders'); - } - - - public function testGetRelationProperlySetsNestedRelationshipsWithSimilarNames() - { - $builder = $this->getBuilder(); - $builder->setModel($this->getMockModel()); - $builder->getModel()->shouldReceive('orders')->once()->andReturn($relation = m::mock('stdClass')); - $builder->getModel()->shouldReceive('ordersGroups')->once()->andReturn($groupsRelation = m::mock('stdClass')); - - $relationQuery = m::mock('stdClass'); - $relation->shouldReceive('getQuery')->andReturn($relationQuery); - - $groupRelationQuery = m::mock('stdClass'); - $groupsRelation->shouldReceive('getQuery')->andReturn($groupRelationQuery); - $groupRelationQuery->shouldReceive('with')->once()->with(['lines' => null, 'lines.details' => null]); - - $builder->setEagerLoads( - ['orders' => null, 'ordersGroups' => null, 'ordersGroups.lines' => null, 'ordersGroups.lines.details' => null] - ); - - $builder->getRelation('orders'); - $builder->getRelation('ordersGroups'); - } - - - public function testEagerLoadParsingSetsProperRelationships() - { - $builder = $this->getBuilder(); - $builder->with(['orders', 'orders.lines']); - $eagers = $builder->getEagerLoads(); - - $this->assertEquals(['orders', 'orders.lines'], array_keys($eagers)); - $this->assertInstanceOf('Closure', $eagers['orders']); - $this->assertInstanceOf('Closure', $eagers['orders.lines']); - - $builder = $this->getBuilder(); - $builder->with('orders', 'orders.lines'); - $eagers = $builder->getEagerLoads(); - - $this->assertEquals(['orders', 'orders.lines'], array_keys($eagers)); - $this->assertInstanceOf('Closure', $eagers['orders']); - $this->assertInstanceOf('Closure', $eagers['orders.lines']); - - $builder = $this->getBuilder(); - $builder->with(['orders.lines']); - $eagers = $builder->getEagerLoads(); - - $this->assertEquals(['orders', 'orders.lines'], array_keys($eagers)); - $this->assertInstanceOf('Closure', $eagers['orders']); - $this->assertInstanceOf('Closure', $eagers['orders.lines']); - - $builder = $this->getBuilder(); - $builder->with(['orders' => function() { return 'foo'; }]); - $eagers = $builder->getEagerLoads(); - - $this->assertEquals('foo', $eagers['orders']()); - - $builder = $this->getBuilder(); - $builder->with(['orders.lines' => function() { return 'foo'; }]); - $eagers = $builder->getEagerLoads(); - - $this->assertInstanceOf('Closure', $eagers['orders']); - $this->assertNull($eagers['orders']()); - $this->assertEquals('foo', $eagers['orders.lines']()); - } - - - public function testQueryPassThru() - { - $builder = $this->getBuilder(); - $builder->getQuery()->shouldReceive('foobar')->once()->andReturn('foo'); - - $this->assertInstanceOf(Builder::class, $builder->foobar()); - - $builder = $this->getBuilder(); - $builder->getQuery()->shouldReceive('insert')->once()->with(['bar'])->andReturn('foo'); - - $this->assertEquals('foo', $builder->insert(['bar'])); - } - - - public function testQueryScopes() - { - $builder = $this->getBuilder(); - $builder->getQuery()->shouldReceive('from'); - $builder->getQuery()->shouldReceive('where')->once()->with('foo', 'bar'); - $builder->setModel($model = new EloquentBuilderTestScopeStub); - $result = $builder->approved(); - - $this->assertEquals($builder, $result); - } - - - public function testNestedWhere() - { - $nestedQuery = m::mock(Builder::class); - $nestedRawQuery = $this->getMockQueryBuilder(); - $nestedQuery->shouldReceive('getQuery')->once()->andReturn($nestedRawQuery); - $model = $this->getMockModel()->makePartial(); - $model->shouldReceive('newQueryWithoutScopes')->once()->andReturn($nestedQuery); - $builder = $this->getBuilder(); - $builder->getQuery()->shouldReceive('from'); - $builder->setModel($model); - $builder->getQuery()->shouldReceive('addNestedWhereQuery')->once()->with($nestedRawQuery, 'and'); - $nestedQuery->shouldReceive('foo')->once(); - - $result = $builder->where(function($query) { $query->foo(); }); - $this->assertEquals($builder, $result); - } - - - public function testRealNestedWhereWithScopes() - { - $model = new EloquentBuilderTestNestedStub; - $this->mockConnectionForModel($model, 'SQLite'); - $query = $model->newQuery()->where('foo', '=', 'bar')->where(function($query) { $query->where('baz', '>', 9000); }); - $this->assertEquals('select * from "table" where "table"."deleted_at" is null and "foo" = ? and ("baz" > ?)', $query->toSql()); - $this->assertEquals(['bar', 9000], $query->getBindings()); - } - - - public function testSimpleWhere() - { - $builder = $this->getBuilder(); - $builder->getQuery()->shouldReceive('where')->once()->with('foo', '=', 'bar'); - $result = $builder->where('foo', '=', 'bar'); - $this->assertEquals($result, $builder); - } - - - public function testDeleteOverride() - { - $builder = $this->getBuilder(); - $builder->onDelete(function($builder) - { - return ['foo' => $builder]; - }); - $this->assertEquals(['foo' => $builder], $builder->delete()); - } - - - public function testHasNestedWithConstraints() - { - $model = new EloquentBuilderTestModelParentStub; - - $builder = $model->whereHas('foo', function ($q) { - $q->whereHas('bar', function ($q) { - $q->where('baz', 'bam'); - }); - })->toSql(); - - $result = $model->whereHas('foo.bar', function ($q) { - $q->where('baz', 'bam'); - })->toSql(); - - $this->assertEquals($builder, $result); - } - - - public function testHasNested() - { - $model = new EloquentBuilderTestModelParentStub; - - $builder = $model->whereHas('foo', function ($q) { - $q->has('bar'); - }); - - $result = $model->has('foo.bar')->toSql(); - - $this->assertEquals($builder->toSql(), $result); - } - - - protected function mockConnectionForModel($model, $database) - { - $grammarClass = 'Illuminate\Database\Query\Grammars\\'.$database.'Grammar'; - $processorClass = 'Illuminate\Database\Query\Processors\\'.$database.'Processor'; - $grammar = new $grammarClass; - $processor = new $processorClass; - $connection = m::mock(Connection::class, ['getQueryGrammar' => $grammar, 'getPostProcessor' => $processor] - ); - $resolver = m::mock(ConnectionResolverInterface::class, ['connection' => $connection]); - $class = get_class($model); - $class::setConnectionResolver($resolver); - } - - - protected function getBuilder() - { - return new Builder($this->getMockQueryBuilder()); - } - - - protected function getMockModel() - { - $model = m::mock(Model::class); - $model->shouldReceive('getKeyName')->andReturn('foo'); - $model->shouldReceive('getTable')->andReturn('foo_table'); - $model->shouldReceive('getQualifiedKeyName')->andReturn('foo_table.foo'); - return $model; - } - - - protected function getMockQueryBuilder() - { - $query = m::mock(\Illuminate\Database\Query\Builder::class); - $query->shouldReceive('from')->with('foo_table'); - return $query; - } - -} - -class EloquentBuilderTestModelStub extends Illuminate\Database\Eloquent\Model {} - -class EloquentBuilderTestScopeStub extends Illuminate\Database\Eloquent\Model { - public function scopeApproved($query) - { - $query->where('foo', 'bar'); - } -} - -class EloquentBuilderTestWithTrashedStub extends Illuminate\Database\Eloquent\Model { - use Illuminate\Database\Eloquent\SoftDeletes; - protected string $table = 'table'; - #[\Override] - public function getKeyName(): string { return 'foo'; } -} - -class EloquentBuilderTestNestedStub extends Illuminate\Database\Eloquent\Model { - protected string $table = 'table'; - use Illuminate\Database\Eloquent\SoftDeletes; -} - -class EloquentBuilderTestListsStub { - protected $attributes; - public function __construct($attributes) - { - $this->attributes = $attributes; - } - public function __get($key) - { - return 'foo_' . $this->attributes[$key]; - } -} - -class EloquentBuilderTestModelParentStub extends Illuminate\Database\Eloquent\Model { - public function foo() - { - return $this->belongsTo('EloquentBuilderTestModelCloseRelatedStub'); - } -} - -class EloquentBuilderTestModelCloseRelatedStub extends Illuminate\Database\Eloquent\Model { - public function bar() - { - return $this->hasMany('EloquentBuilderTestModelFarRelatedStub'); - } -} - -class EloquentBuilderTestModelFarRelatedStub extends Illuminate\Database\Eloquent\Model {} diff --git a/tests/Database/DatabaseEloquentCollectionTest.php b/tests/Database/DatabaseEloquentCollectionTest.php deleted file mode 100755 index f488bac9d..000000000 --- a/tests/Database/DatabaseEloquentCollectionTest.php +++ /dev/null @@ -1,225 +0,0 @@ -add('bar')->add('baz'); - $this->assertEquals(['foo', 'bar', 'baz'], $c->all()); - } - - - public function testGettingMaxItemsFromCollection() - { - $c = new Collection([(object) ['foo' => 10], (object) ['foo' => 20]]); - $this->assertEquals(20, $c->max('foo')); - } - - - public function testGettingMinItemsFromCollection() - { - $c = new Collection([(object) ['foo' => 10], (object) ['foo' => 20]]); - $this->assertEquals(10, $c->min('foo')); - } - - - public function testContainsIndicatesIfModelInArray() - { - $mockModel = m::mock(Model::class); - $mockModel->shouldReceive('getKey')->andReturn(1); - $mockModel2 = m::mock(Model::class); - $mockModel2->shouldReceive('getKey')->andReturn(2); - $mockModel3 = m::mock(Model::class); - $mockModel3->shouldReceive('getKey')->andReturn(3); - $c = new Collection([$mockModel, $mockModel2]); - - $this->assertTrue($c->contains($mockModel)); - $this->assertTrue($c->contains($mockModel2)); - $this->assertFalse($c->contains($mockModel3)); - } - - - public function testContainsIndicatesIfKeyedModelInArray() - { - $mockModel = m::mock(Model::class); - $mockModel->shouldReceive('getKey')->andReturn(1); - $c = new Collection([$mockModel]); - $mockModel2 = m::mock(Model::class); - $mockModel2->shouldReceive('getKey')->andReturn(2); - $c->add($mockModel2); - - $this->assertTrue($c->contains(1)); - $this->assertTrue($c->contains(2)); - $this->assertFalse($c->contains(3)); - } - - - public function testFindMethodFindsModelById() - { - $mockModel = m::mock(Model::class); - $mockModel->shouldReceive('getKey')->andReturn(1); - $c = new Collection([$mockModel]); - - $this->assertSame($mockModel, $c->find(1)); - $this->assertSame('taylor', $c->find(2, 'taylor')); - } - - - public function testLoadMethodEagerLoadsGivenRelationships() - { - $c = $this->getMock(Collection::class, ['first'], [['foo']]); - $mockItem = m::mock('StdClass'); - $c->expects($this->once())->method('first')->willReturn($mockItem); - $mockItem->shouldReceive('newQuery')->once()->andReturn($mockItem); - $mockItem->shouldReceive('with')->with(['bar', 'baz'])->andReturn($mockItem); - $mockItem->shouldReceive('eagerLoadRelations')->once()->with(['foo'])->andReturn(['results']); - $c->load('bar', 'baz'); - - $this->assertEquals(['results'], $c->all()); - } - - - public function testCollectionDictionaryReturnsModelKeys() - { - $one = m::mock(Model::class); - $one->shouldReceive('getKey')->andReturn(1); - - $two = m::mock(Model::class); - $two->shouldReceive('getKey')->andReturn(2); - - $three = m::mock(Model::class); - $three->shouldReceive('getKey')->andReturn(3); - - $c = new Collection([$one, $two, $three]); - - $this->assertEquals([1,2,3], $c->modelKeys()); - } - - - public function testCollectionMergesWithGivenCollection() - { - $one = m::mock(Model::class); - $one->shouldReceive('getKey')->andReturn(1); - - $two = m::mock(Model::class); - $two->shouldReceive('getKey')->andReturn(2); - - $three = m::mock(Model::class); - $three->shouldReceive('getKey')->andReturn(3); - - $c1 = new Collection([$one, $two]); - $c2 = new Collection([$two, $three]); - - $this->assertEquals(new Collection([$one, $two, $three]), $c1->merge($c2)); - } - - - public function testCollectionDiffsWithGivenCollection() - { - $one = m::mock(Model::class); - $one->shouldReceive('getKey')->andReturn(1); - - $two = m::mock(Model::class); - $two->shouldReceive('getKey')->andReturn(2); - - $three = m::mock(Model::class); - $three->shouldReceive('getKey')->andReturn(3); - - $c1 = new Collection([$one, $two]); - $c2 = new Collection([$two, $three]); - - $this->assertEquals(new Collection([$one]), $c1->diff($c2)); - } - - - public function testCollectionIntersectsWithGivenCollection() - { - $one = m::mock(Model::class); - $one->shouldReceive('getKey')->andReturn(1); - - $two = m::mock(Model::class); - $two->shouldReceive('getKey')->andReturn(2); - - $three = m::mock(Model::class); - $three->shouldReceive('getKey')->andReturn(3); - - $c1 = new Collection([$one, $two]); - $c2 = new Collection([$two, $three]); - - $this->assertEquals(new Collection([$two]), $c1->intersect($c2)); - } - - - public function testCollectionReturnsUniqueItems() - { - $one = m::mock(Model::class); - $one->shouldReceive('getKey')->andReturn(1); - - $two = m::mock(Model::class); - $two->shouldReceive('getKey')->andReturn(2); - - $c = new Collection([$one, $two, $two]); - - $this->assertEquals(new Collection([$one, $two]), $c->unique()); - } - - - public function testLists() - { - $data = new Collection( - [(object) ['name' => 'taylor', 'email' => 'foo'], (object) ['name' => 'dayle', 'email' => 'bar']] - ); - $this->assertEquals(['taylor' => 'foo', 'dayle' => 'bar'], $data->lists('email', 'name')); - $this->assertEquals(['foo', 'bar'], $data->lists('email')); - } - - - public function testOnlyReturnsCollectionWithGivenModelKeys() - { - $one = m::mock(Model::class); - $one->shouldReceive('getKey')->andReturn(1); - - $two = m::mock(Model::class); - $two->shouldReceive('getKey')->andReturn(2); - - $three = m::mock(Model::class); - $three->shouldReceive('getKey')->andReturn(3); - - $c = new Collection([$one, $two, $three]); - - $this->assertEquals(new Collection([$one]), $c->only(1)); - $this->assertEquals(new Collection([$two, $three]), $c->only([2, 3])); - } - - - public function testExceptReturnsCollectionWithoutGivenModelKeys() - { - $one = m::mock(Model::class); - $one->shouldReceive('getKey')->andReturn(1); - - $two = m::mock(Model::class); - $two->shouldReceive('getKey')->andReturn('2'); - - $three = m::mock(Model::class); - $three->shouldReceive('getKey')->andReturn(3); - - $c = new Collection([$one, $two, $three]); - - $this->assertEquals(new Collection([$one, $three]), $c->except(2)); - $this->assertEquals(new Collection([$one]), $c->except([2, 3])); - } - -} diff --git a/tests/Database/DatabaseEloquentHasManyTest.php b/tests/Database/DatabaseEloquentHasManyTest.php deleted file mode 100755 index 9b1d6565f..000000000 --- a/tests/Database/DatabaseEloquentHasManyTest.php +++ /dev/null @@ -1,115 +0,0 @@ -getRelation(); - $created = $this->getMock(Model::class, ['save', 'getKey', 'setAttribute']); - $created->expects($this->once())->method('save')->willReturn(true); - $relation->getRelated()->shouldReceive('newInstance')->once()->with(['name' => 'taylor'])->andReturn($created); - $created->expects($this->once())->method('setAttribute')->with('foreign_key', 1); - - $this->assertEquals($created, $relation->create(['name' => 'taylor'])); - } - - - public function testUpdateMethodUpdatesModelsWithTimestamps() - { - $relation = $this->getRelation(); - $relation->getRelated()->shouldReceive('usesTimestamps')->once()->andReturn(true); - $relation->getRelated()->shouldReceive('freshTimestamp')->once()->andReturn($carbon = new Carbon()); - $relation->getRelated()->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at'); - $relation->getQuery()->shouldReceive('update')->once()->with(['foo' => 'bar', 'updated_at' => $carbon])->andReturn('results'); - - $this->assertEquals('results', $relation->update(['foo' => 'bar'])); - } - - - public function testRelationIsProperlyInitialized() - { - $relation = $this->getRelation(); - $model = m::mock(Model::class); - $relation->getRelated()->shouldReceive('newCollection')->andReturnUsing(function($array = []) { return new Collection($array); }); - $model->shouldReceive('setRelation')->once()->with('foo', m::type(Collection::class)); - $models = $relation->initRelation([$model], 'foo'); - - $this->assertEquals([$model], $models); - } - - - public function testEagerConstraintsAreProperlyAdded() - { - $relation = $this->getRelation(); - $relation->getQuery()->shouldReceive('whereIn')->once()->with('table.foreign_key', [1, 2]); - $model1 = new EloquentHasManyModelStub; - $model1->id = 1; - $model2 = new EloquentHasManyModelStub; - $model2->id = 2; - $relation->addEagerConstraints([$model1, $model2]); - } - - - public function testModelsAreProperlyMatchedToParents() - { - $relation = $this->getRelation(); - - $result1 = new EloquentHasManyModelStub; - $result1->foreign_key = 1; - $result2 = new EloquentHasManyModelStub; - $result2->foreign_key = 2; - $result3 = new EloquentHasManyModelStub; - $result3->foreign_key = 2; - - $model1 = new EloquentHasManyModelStub; - $model1->id = 1; - $model2 = new EloquentHasManyModelStub; - $model2->id = 2; - $model3 = new EloquentHasManyModelStub; - $model3->id = 3; - - $relation->getRelated()->shouldReceive('newCollection')->andReturnUsing(function($array) { return new Collection($array); }); - $models = $relation->match([$model1, $model2, $model3], new Collection([$result1, $result2, $result3]), 'foo'); - - $this->assertEquals(1, $models[0]->foo[0]->foreign_key); - $this->assertCount(1, $models[0]->foo); - $this->assertEquals(2, $models[1]->foo[0]->foreign_key); - $this->assertEquals(2, $models[1]->foo[1]->foreign_key); - $this->assertCount(2, $models[1]->foo); - $this->assertEmpty($models[2]->foo); - } - - - protected function getRelation() - { - $builder = m::mock(Builder::class); - $builder->shouldReceive('where')->with('table.foreign_key', '=', 1); - $related = m::mock(Model::class); - $builder->shouldReceive('getModel')->andReturn($related); - $parent = m::mock(Model::class); - $parent->shouldReceive('getAttribute')->with('id')->andReturn(1); - $parent->shouldReceive('getCreatedAtColumn')->andReturn('created_at'); - $parent->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at'); - return new HasMany($builder, $parent, 'table.foreign_key', 'id'); - } - -} - -class EloquentHasManyModelStub extends Illuminate\Database\Eloquent\Model { - public $foreign_key = 'foreign.value'; -} diff --git a/tests/Database/DatabaseEloquentHasManyThroughTest.php b/tests/Database/DatabaseEloquentHasManyThroughTest.php deleted file mode 100644 index 98906fd11..000000000 --- a/tests/Database/DatabaseEloquentHasManyThroughTest.php +++ /dev/null @@ -1,104 +0,0 @@ -getRelation(); - $model = m::mock(Model::class); - $relation->getRelated()->shouldReceive('newCollection')->andReturnUsing( - function ($array = []) { - return new Collection($array); - } - ); - $model->shouldReceive('setRelation')->once()->with('foo', m::type(Collection::class)); - $models = $relation->initRelation([$model], 'foo'); - - $this->assertEquals([$model], $models); - } - - - public function testEagerConstraintsAreProperlyAdded() - { - $relation = $this->getRelation(); - $relation->getQuery()->shouldReceive('whereIn')->once()->with('users.country_id', [1, 2]); - $model1 = new EloquentHasManyThroughModelStub; - $model1->id = 1; - $model2 = new EloquentHasManyThroughModelStub; - $model2->id = 2; - $relation->addEagerConstraints([$model1, $model2]); - } - - - public function testModelsAreProperlyMatchedToParents() - { - $relation = $this->getRelation(); - - $result1 = new EloquentHasManyThroughModelStub; - $result1->country_id = 1; - $result2 = new EloquentHasManyThroughModelStub; - $result2->country_id = 2; - $result3 = new EloquentHasManyThroughModelStub; - $result3->country_id = 2; - - $model1 = new EloquentHasManyThroughModelStub; - $model1->id = 1; - $model2 = new EloquentHasManyThroughModelStub; - $model2->id = 2; - $model3 = new EloquentHasManyThroughModelStub; - $model3->id = 3; - - $relation->getRelated()->shouldReceive('newCollection')->andReturnUsing(function($array) { return new Collection($array); }); - $models = $relation->match([$model1, $model2, $model3], new Collection([$result1, $result2, $result3]), 'foo'); - - $this->assertEquals(1, $models[0]->foo[0]->country_id); - $this->assertCount(1, $models[0]->foo); - $this->assertEquals(2, $models[1]->foo[0]->country_id); - $this->assertEquals(2, $models[1]->foo[1]->country_id); - $this->assertCount(2, $models[1]->foo); - $this->assertEmpty($models[2]->foo); - } - - - protected function getRelation() - { - $builder = m::mock(Builder::class); - $builder->shouldReceive('join')->once()->with('users', 'users.id', '=', 'posts.user_id'); - $builder->shouldReceive('where')->with('users.country_id', '=', 1); - - $country = m::mock(Model::class); - $country->shouldReceive('getKey')->andReturn(1); - $country->shouldReceive('getForeignKey')->andReturn('country_id'); - $user = m::mock(Model::class); - $user->shouldReceive('getTable')->andReturn('users'); - $user->shouldReceive('getQualifiedKeyName')->andReturn('users.id'); - $post = m::mock(Model::class); - $post->shouldReceive('getTable')->andReturn('posts'); - - $builder->shouldReceive('getModel')->andReturn($post); - - $user->shouldReceive('getKey')->andReturn(1); - $user->shouldReceive('getCreatedAtColumn')->andReturn('created_at'); - $user->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at'); - return new HasManyThrough($builder, $country, $user, 'country_id', 'user_id'); - } - -} - -class EloquentHasManyThroughModelStub extends Illuminate\Database\Eloquent\Model { - public $country_id = 'foreign.value'; -} diff --git a/tests/Database/DatabaseEloquentHasOneTest.php b/tests/Database/DatabaseEloquentHasOneTest.php deleted file mode 100755 index be3792d3b..000000000 --- a/tests/Database/DatabaseEloquentHasOneTest.php +++ /dev/null @@ -1,139 +0,0 @@ -getRelation(); - $mockModel = $this->getMock(Model::class, ['save']); - $mockModel->expects($this->once())->method('save')->willReturn(true); - $result = $relation->save($mockModel); - - $attributes = $result->getAttributes(); - $this->assertEquals(1, $attributes['foreign_key']); - } - - - public function testCreateMethodProperlyCreatesNewModel() - { - $relation = $this->getRelation(); - $created = $this->getMock(Model::class, ['save', 'getKey', 'setAttribute']); - $created->expects($this->once())->method('save')->willReturn(true); - $relation->getRelated()->shouldReceive('newInstance')->once()->with(['name' => 'taylor'])->andReturn($created); - $created->expects($this->once())->method('setAttribute')->with('foreign_key', 1); - - $this->assertEquals($created, $relation->create(['name' => 'taylor'])); - } - - - public function testUpdateMethodUpdatesModelsWithTimestamps() - { - $relation = $this->getRelation(); - $relation->getRelated()->shouldReceive('usesTimestamps')->once()->andReturn(true); - $relation->getRelated()->shouldReceive('freshTimestamp')->once()->andReturn($carbon = new Carbon()); - $relation->getRelated()->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at'); - $relation->getQuery()->shouldReceive('update')->once()->with(['foo' => 'bar', 'updated_at' => $carbon])->andReturn('results'); - - $this->assertEquals('results', $relation->update(['foo' => 'bar'])); - } - - - public function testRelationIsProperlyInitialized() - { - $relation = $this->getRelation(); - $model = m::mock(Model::class); - $model->shouldReceive('setRelation')->once()->with('foo', null); - $models = $relation->initRelation([$model], 'foo'); - - $this->assertEquals([$model], $models); - } - - - public function testEagerConstraintsAreProperlyAdded() - { - $relation = $this->getRelation(); - $relation->getQuery()->shouldReceive('whereIn')->once()->with('table.foreign_key', [1, 2]); - $model1 = new EloquentHasOneModelStub; - $model1->id = 1; - $model2 = new EloquentHasOneModelStub; - $model2->id = 2; - $relation->addEagerConstraints([$model1, $model2]); - } - - - public function testModelsAreProperlyMatchedToParents() - { - $relation = $this->getRelation(); - - $result1 = new EloquentHasOneModelStub; - $result1->foreign_key = 1; - $result2 = new EloquentHasOneModelStub; - $result2->foreign_key = 2; - - $model1 = new EloquentHasOneModelStub; - $model1->id = 1; - $model2 = new EloquentHasOneModelStub; - $model2->id = 2; - $model3 = new EloquentHasOneModelStub; - $model3->id = 3; - - $models = $relation->match([$model1, $model2, $model3], new Collection([$result1, $result2]), 'foo'); - - $this->assertEquals(1, $models[0]->foo->foreign_key); - $this->assertEquals(2, $models[1]->foo->foreign_key); - $this->assertNull($models[2]->foo); - } - - - public function testRelationCountQueryCanBeBuilt() - { - $relation = $this->getRelation(); - $query = m::mock(Builder::class); - $query->shouldReceive('select')->once()->with(m::type(Expression::class)); - $relation->getParent()->shouldReceive('getTable')->andReturn('table'); - $query->shouldReceive('where')->once()->with('table.foreign_key', '=', m::type( - Expression::class - )); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($parentQuery = m::mock('StdClass')); - $parentQuery->shouldReceive('getGrammar')->once()->andReturn($grammar = m::mock('StdClass')); - $grammar->shouldReceive('wrap')->once()->with('table.id'); - - $relation->getRelationCountQuery($query, $query); - } - - - protected function getRelation() - { - $builder = m::mock(Builder::class); - $builder->shouldReceive('where')->with('table.foreign_key', '=', 1); - $related = m::mock(Model::class); - $builder->shouldReceive('getModel')->andReturn($related); - $parent = m::mock(Model::class); - $parent->shouldReceive('getAttribute')->with('id')->andReturn(1); - $parent->shouldReceive('getCreatedAtColumn')->andReturn('created_at'); - $parent->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at'); - $parent->shouldReceive('newQueryWithoutScopes')->andReturn($builder); - return new HasOne($builder, $parent, 'table.foreign_key', 'id'); - } - -} - -class EloquentHasOneModelStub extends Illuminate\Database\Eloquent\Model { - public $foreign_key = 'foreign.value'; -} diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php deleted file mode 100755 index 11f5e6397..000000000 --- a/tests/Database/DatabaseEloquentModelTest.php +++ /dev/null @@ -1,1190 +0,0 @@ -name = 'foo'; - $this->assertEquals('foo', $model->name); - $this->assertTrue(isset($model->name)); - unset($model->name); - $this->assertFalse(isset($model->name)); - - // test mutation - $model->list_items = ['name' => 'taylor']; - $this->assertEquals(['name' => 'taylor'], $model->list_items); - $attributes = $model->getAttributes(); - $this->assertEquals(json_encode(['name' => 'taylor']), $attributes['list_items']); - } - - - public function testDirtyAttributes(): void - { - $model = new EloquentModelStub(['foo' => '1', 'bar' => 2, 'baz' => 3]); - $model->syncOriginal(); - $model->foo = 1; - $model->bar = 20; - $model->baz = 30; - - $this->assertTrue($model->isDirty()); - $this->assertFalse($model->isDirty('foo')); - $this->assertTrue($model->isDirty('bar')); - $this->assertTrue($model->isDirty('foo', 'bar')); - $this->assertTrue($model->isDirty(['foo', 'bar'])); - } - - - public function testCalculatedAttributes(): void - { - $model = new EloquentModelStub; - $model->password = 'secret'; - $attributes = $model->getAttributes(); - - // ensure password attribute was not set to null - $this->assertFalse(array_key_exists('password', $attributes)); - $this->assertEquals('******', $model->password); - $this->assertEquals('5ebe2294ecd0e0f08eab7690d2a6ee69', $attributes['password_hash']); - $this->assertEquals('5ebe2294ecd0e0f08eab7690d2a6ee69', $model->password_hash); - } - - - public function testNewInstanceReturnsNewInstanceWithAttributesSet(): void - { - $model = new EloquentModelStub; - $instance = $model->newInstance(['name' => 'taylor']); - $this->assertInstanceOf('EloquentModelStub', $instance); - $this->assertEquals('taylor', $instance->name); - } - - - public function testHydrateCreatesCollectionOfModels(): void - { - $data = [['name' => 'Taylor'], ['name' => 'Otwell']]; - $collection = EloquentModelStub::hydrate($data); - - $this->assertInstanceOf(Collection::class, $collection); - $this->assertCount(2, $collection); - $this->assertInstanceOf('EloquentModelStub', $collection[0]); - $this->assertInstanceOf('EloquentModelStub', $collection[1]); - $this->assertEquals('Taylor', $collection[0]->name); - $this->assertEquals('Otwell', $collection[1]->name); - } - - - public function testHydrateRawMakesRawQuery(): void - { - $collection = EloquentModelHydrateRawStub::hydrateRaw('SELECT ?', ['foo']); - $this->assertEquals('hydrated', $collection[0]); - } - - - public function testCreateMethodSavesNewModel(): void - { - $_SERVER['__eloquent.saved'] = false; - $model = EloquentModelSaveStub::create(['name' => 'taylor']); - $this->assertTrue($_SERVER['__eloquent.saved']); - $this->assertEquals('taylor', $model->name); - } - - - public function testFindMethodCallsQueryBuilderCorrectly(): void - { - $result = EloquentModelFindStub::find(1); - $this->assertEquals('foo', $result); - } - - - public function testFindMethodUseWritePdo(): void - { - EloquentModelFindWithWritePdoStub::onWriteConnection()->find(1); - } - - - public function testFindOrFailMethodThrowsModelNotFoundException(): void - { - $this->expectException(Illuminate\Database\Eloquent\ModelNotFoundException::class); - $result = EloquentModelFindNotFoundStub::findOrFail(1); - } - - - public function testFindMethodWithArrayCallsQueryBuilderCorrectly(): void - { - $result = EloquentModelFindManyStub::find([1, 2]); - $this->assertEquals('foo', $result); - } - - - public function testDestroyMethodCallsQueryBuilderCorrectly(): void - { - $result = EloquentModelDestroyStub::destroy(1, 2, 3); - } - - - public function testWithMethodCallsQueryBuilderCorrectly(): void - { - $result = EloquentModelWithStub::with('foo', 'bar'); - $this->assertEquals('foo', $result); - } - - - public function testWithMethodCallsQueryBuilderCorrectlyWithArray(): void - { - $result = EloquentModelWithStub::with(['foo', 'bar']); - $this->assertEquals('foo', $result); - } - - - public function testUpdateProcess(): void - { - $model = $this->getMock('EloquentModelStub', ['newQueryWithoutScopes', 'updateTimestamps']); - $query = m::mock(Builder::class); - $query->shouldReceive('where')->once()->with('id', '=', 1); - $query->shouldReceive('update')->once()->with(['name' => 'taylor']); - $model->expects($this->once())->method('newQueryWithoutScopes')->willReturn($query); - $model->expects($this->once())->method('updateTimestamps'); - $model->setEventDispatcher($events = m::mock(Dispatcher::class)); - $events->shouldReceive('until')->once()->with('eloquent.saving: '.get_class($model), $model)->andReturn(true); - $events->shouldReceive('until')->once()->with('eloquent.updating: '.get_class($model), $model)->andReturn(true); - $events->shouldReceive('dispatch')->once()->with('eloquent.updated: '.get_class($model), $model)->andReturn(true); - $events->shouldReceive('dispatch')->once()->with('eloquent.saved: '.get_class($model), $model)->andReturn(true); - - $model->id = 1; - $model->foo = 'bar'; - // make sure foo isn't synced so we can test that dirty attributes only are updated - $model->syncOriginal(); - $model->name = 'taylor'; - $model->exists = true; - $this->assertTrue($model->save()); - } - - - public function testUpdateProcessDoesntOverrideTimestamps(): void - { - $model = $this->getMock('EloquentModelStub', ['newQueryWithoutScopes']); - $query = m::mock(Builder::class); - $query->shouldReceive('where')->once()->with('id', '=', 1); - $query->shouldReceive('update')->once()->with(['created_at' => 'foo', 'updated_at' => 'bar']); - $model->expects($this->once())->method('newQueryWithoutScopes')->willReturn($query); - $model->setEventDispatcher($events = m::mock(Dispatcher::class)); - $events->shouldReceive('until'); - $events->shouldReceive('dispatch'); - - $model->id = 1; - $model->syncOriginal(); - $model->created_at = 'foo'; - $model->updated_at = 'bar'; - $model->exists = true; - $this->assertTrue($model->save()); - } - - - public function testSaveIsCancelledIfSavingEventReturnsFalse(): void - { - $model = $this->getMock('EloquentModelStub', ['newQueryWithoutScopes']); - $query = m::mock(Builder::class); - $model->expects($this->once())->method('newQueryWithoutScopes')->willReturn($query); - $model->setEventDispatcher($events = m::mock(Dispatcher::class)); - $events->shouldReceive('until')->once()->with('eloquent.saving: '.get_class($model), $model)->andReturn(false); - $model->exists = true; - - $this->assertFalse($model->save()); - } - - - public function testUpdateIsCancelledIfUpdatingEventReturnsFalse(): void - { - $model = $this->getMock('EloquentModelStub', ['newQueryWithoutScopes']); - $query = m::mock(Builder::class); - $model->expects($this->once())->method('newQueryWithoutScopes')->willReturn($query); - $model->setEventDispatcher($events = m::mock(Dispatcher::class)); - $events->shouldReceive('until')->once()->with('eloquent.saving: '.get_class($model), $model)->andReturn(true); - $events->shouldReceive('until')->once()->with('eloquent.updating: '.get_class($model), $model)->andReturn(false); - $model->exists = true; - $model->foo = 'bar'; - - $this->assertFalse($model->save()); - } - - - public function testUpdateProcessWithoutTimestamps(): void - { - $model = $this->getMock('EloquentModelStub', ['newQueryWithoutScopes', 'updateTimestamps', 'fireModelEvent']); - $model->timestamps = false; - $query = m::mock(Builder::class); - $query->shouldReceive('where')->once()->with('id', '=', 1); - $query->shouldReceive('update')->once()->with(['name' => 'taylor']); - $model->expects($this->once())->method('newQueryWithoutScopes')->willReturn($query); - $model->expects($this->never())->method('updateTimestamps'); - $model->expects($this->any())->method('fireModelEvent')->willReturn(true); - - $model->id = 1; - $model->syncOriginal(); - $model->name = 'taylor'; - $model->exists = true; - $this->assertTrue($model->save()); - } - - - public function testUpdateUsesOldPrimaryKey(): void - { - $model = $this->getMock('EloquentModelStub', ['newQueryWithoutScopes', 'updateTimestamps']); - $query = m::mock(Builder::class); - $query->shouldReceive('where')->once()->with('id', '=', 1); - $query->shouldReceive('update')->once()->with(['id' => 2, 'foo' => 'bar']); - $model->expects($this->once())->method('newQueryWithoutScopes')->willReturn($query); - $model->expects($this->once())->method('updateTimestamps'); - $model->setEventDispatcher($events = m::mock(Dispatcher::class)); - $events->shouldReceive('until')->once()->with('eloquent.saving: '.get_class($model), $model)->andReturn(true); - $events->shouldReceive('until')->once()->with('eloquent.updating: '.get_class($model), $model)->andReturn(true); - $events->shouldReceive('dispatch')->once()->with('eloquent.updated: '.get_class($model), $model)->andReturn(true); - $events->shouldReceive('dispatch')->once()->with('eloquent.saved: '.get_class($model), $model)->andReturn(true); - - $model->id = 1; - $model->syncOriginal(); - $model->id = 2; - $model->foo = 'bar'; - $model->exists = true; - - $this->assertTrue($model->save()); - } - - - public function testTimestampsAreReturnedAsObjects(): void - { - $model = $this->getMock('EloquentDateModelStub', ['getDateFormat']); - $model->expects($this->any())->method('getDateFormat')->willReturn('Y-m-d'); - $model->setRawAttributes([ - 'created_at' => '2012-12-04', - 'updated_at' => '2012-12-05', - ]); - - $this->assertInstanceOf(Carbon::class, $model->created_at); - $this->assertInstanceOf(Carbon::class, $model->updated_at); - } - - - public function testTimestampsAreReturnedAsObjectsFromPlainDatesAndTimestamps(): void - { - $model = $this->getMock('EloquentDateModelStub', ['getDateFormat']); - $model->expects($this->any())->method('getDateFormat')->willReturn('Y-m-d H:i:s'); - $model->setRawAttributes([ - 'created_at' => '2012-12-04', - 'updated_at' => time(), - ]); - - $this->assertInstanceOf(Carbon::class, $model->created_at); - $this->assertInstanceOf(Carbon::class, $model->updated_at); - } - - - public function testTimestampsAreReturnedAsObjectsOnCreate(): void - { - $timestamps = [ - 'created_at' => Carbon::now(), - 'updated_at' => Carbon::now() - ]; - $model = new EloquentDateModelStub; - Illuminate\Database\Eloquent\Model::setConnectionResolver($resolver = m::mock( - ConnectionResolverInterface::class - )); - $mockConnection = m::mock(Connection::class); - $mockConnection->allows()->getQueryGrammar()->andReturns($mockConnection); - $mockConnection->allows()->getDateFormat()->andReturn('Y-m-d H:i:s'); - $resolver->allows()->connection()->withAnyArgs()->andReturn($mockConnection); - - $instance = $model->newInstance($timestamps); - $this->assertInstanceOf(Carbon::class, $instance->updated_at); - $this->assertInstanceOf(Carbon::class, $instance->created_at); - } - - - public function testDateTimeAttributesReturnNullIfSetToNull(): void - { - $timestamps = [ - 'created_at' => Carbon::now(), - 'updated_at' => Carbon::now() - ]; - $model = new EloquentDateModelStub; - Illuminate\Database\Eloquent\Model::setConnectionResolver($resolver = m::mock( - ConnectionResolverInterface::class - )); - $resolver->shouldReceive('connection')->andReturn($mockConnection = m::mock(Connection::class)); - $mockConnection->shouldReceive('getQueryGrammar')->andReturn($mockConnection); - $mockConnection->shouldReceive('getDateFormat')->andReturn('Y-m-d H:i:s'); - $instance = $model->newInstance($timestamps); - - $instance->created_at = null; - $this->assertNull($instance->created_at); - } - - - public function testTimestampsAreCreatedFromStringsAndIntegers(): void - { - $model = new EloquentDateModelStub; - $model->created_at = '2013-05-22 00:00:00'; - $this->assertInstanceOf(Carbon::class, $model->created_at); - - $model = new EloquentDateModelStub; - $model->created_at = time(); - $this->assertInstanceOf(Carbon::class, $model->created_at); - - $model = new EloquentDateModelStub; - $model->created_at = '2012-01-01'; - $this->assertInstanceOf(Carbon::class, $model->created_at); - } - - - public function testInsertProcess(): void - { - $model = $this->getMock('EloquentModelStub', ['newQueryWithoutScopes', 'updateTimestamps']); - $query = m::mock(Builder::class); - $query->shouldReceive('insertGetId')->once()->with(['name' => 'taylor'], 'id')->andReturn(1); - $model->expects($this->once())->method('newQueryWithoutScopes')->willReturn($query); - $model->expects($this->once())->method('updateTimestamps'); - - $model->setEventDispatcher($events = m::mock(Dispatcher::class)); - $events->shouldReceive('until')->once()->with('eloquent.saving: '.get_class($model), $model)->andReturn(true); - $events->shouldReceive('until')->once()->with('eloquent.creating: '.get_class($model), $model)->andReturn(true); - $events->shouldReceive('dispatch')->once()->with('eloquent.created: '.get_class($model), $model); - $events->shouldReceive('dispatch')->once()->with('eloquent.saved: '.get_class($model), $model); - - $model->name = 'taylor'; - $model->exists = false; - $this->assertTrue($model->save()); - $this->assertEquals(1, $model->id); - $this->assertTrue($model->exists); - - $model = $this->getMock('EloquentModelStub', ['newQueryWithoutScopes', 'updateTimestamps']); - $query = m::mock(Builder::class); - $query->shouldReceive('insert')->once()->with(['name' => 'taylor']); - $model->expects($this->once())->method('newQueryWithoutScopes')->willReturn($query); - $model->expects($this->once())->method('updateTimestamps'); - $model->setIncrementing(false); - - $model->setEventDispatcher($events = m::mock(Dispatcher::class)); - $events->shouldReceive('until')->once()->with('eloquent.saving: '.get_class($model), $model)->andReturn(true); - $events->shouldReceive('until')->once()->with('eloquent.creating: '.get_class($model), $model)->andReturn(true); - $events->shouldReceive('dispatch')->once()->with('eloquent.created: '.get_class($model), $model); - $events->shouldReceive('dispatch')->once()->with('eloquent.saved: '.get_class($model), $model); - - $model->name = 'taylor'; - $model->exists = false; - $this->assertTrue($model->save()); - $this->assertNull($model->id); - $this->assertTrue($model->exists); - } - - - public function testInsertIsCancelledIfCreatingEventReturnsFalse(): void - { - $model = $this->getMock('EloquentModelStub', ['newQueryWithoutScopes']); - $query = m::mock(Builder::class); - $model->expects($this->once())->method('newQueryWithoutScopes')->willReturn($query); - $model->setEventDispatcher($events = m::mock(Dispatcher::class)); - $events->shouldReceive('until')->once()->with('eloquent.saving: '.get_class($model), $model)->andReturn(true); - $events->shouldReceive('until')->once()->with('eloquent.creating: '.get_class($model), $model)->andReturn(false); - - $this->assertFalse($model->save()); - $this->assertFalse($model->exists); - } - - - public function testDeleteProperlyDeletesModel(): void - { - $model = $this->getMock(Model::class, ['newQueryWithoutScopes', 'updateTimestamps', 'touchOwners']); - $query = m::mock(Builder::class); - $query->shouldReceive('where')->once()->with('id', 1)->andReturn($query); - $query->shouldReceive('delete')->once(); - $model->expects($this->once())->method('newQueryWithoutScopes')->willReturn($query); - $model->expects($this->once())->method('touchOwners'); - $model->exists = true; - $model->id = 1; - $model->delete(); - } - - - public function testNewQueryReturnsEloquentQueryBuilder(): void - { - $conn = m::mock(Connection::class); - $grammar = m::mock(Grammar::class); - $processor = m::mock(Processor::class); - $conn->shouldReceive('getQueryGrammar')->once()->andReturn($grammar); - $conn->shouldReceive('getPostProcessor')->once()->andReturn($processor); - EloquentModelStub::setConnectionResolver($resolver = m::mock( - ConnectionResolverInterface::class - )); - $resolver->shouldReceive('connection')->andReturn($conn); - $model = new EloquentModelStub; - $builder = $model->newQuery(); - $this->assertInstanceOf(Builder::class, $builder); - } - - - public function testGetAndSetTableOperations(): void - { - $model = new EloquentModelStub; - $this->assertEquals('stub', $model->getTable()); - $model->setTable('foo'); - $this->assertEquals('foo', $model->getTable()); - } - - - public function testGetKeyReturnsValueOfPrimaryKey(): void - { - $model = new EloquentModelStub; - $model->id = 1; - $this->assertEquals(1, $model->getKey()); - $this->assertEquals('id', $model->getKeyName()); - } - - - public function testConnectionManagement(): void - { - EloquentModelStub::setConnectionResolver($resolver = m::mock( - ConnectionResolverInterface::class - )); - $model = new EloquentModelStub; - $model->setConnection('foo'); - $resolver->shouldReceive('connection')->once()->with('foo')->andReturn($connection = m::mock(Connection::class)); - - $this->assertEquals($connection, $model->getConnection()); - } - - - public function testToArray(): void - { - $model = new EloquentModelStub; - $model->name = 'foo'; - $model->age = null; - $model->password = 'password1'; - $model->setHidden(['password']); - $model->setRelation('names', new Illuminate\Database\Eloquent\Collection([ - new EloquentModelStub(['bar' => 'baz']), new EloquentModelStub(['bam' => 'boom']) - ])); - $model->setRelation('partner', new EloquentModelStub(['name' => 'abby'])); - $model->setRelation('group', null); - $model->setRelation('multi', new Illuminate\Database\Eloquent\Collection); - $array = $model->toArray(); - - $this->assertIsArray($array); - $this->assertEquals('foo', $array['name']); - $this->assertEquals('baz', $array['names'][0]['bar']); - $this->assertEquals('boom', $array['names'][1]['bam']); - $this->assertEquals('abby', $array['partner']['name']); - $this->assertNull($array['group']); - $this->assertEquals([], $array['multi']); - $this->assertFalse(isset($array['password'])); - - $model->setAppends(['appendable']); - $array = $model->toArray(); - $this->assertEquals('appended', $array['appendable']); - } - - - public function testToArrayIncludesDefaultFormattedTimestamps(): void - { - $model = new EloquentDateModelStub; - $model->setRawAttributes([ - 'created_at' => '2012-12-04', - 'updated_at' => '2012-12-05', - ]); - - $array = $model->toArray(); - - $this->assertEquals('2012-12-04 00:00:00', $array['created_at']); - $this->assertEquals('2012-12-05 00:00:00', $array['updated_at']); - } - - - public function testToArrayIncludesCustomFormattedTimestamps(): void - { - $model = new EloquentDateModelStub; - $model->setRawAttributes([ - 'created_at' => '2012-12-04', - 'updated_at' => '2012-12-05', - ]); - - $array = $model->toArray(); - - $this->assertEquals('2012-12-04 00:00:00', $array['created_at']); - $this->assertEquals('2012-12-05 00:00:00', $array['updated_at']); - } - - - public function testVisibleCreatesArrayWhitelist(): void - { - $model = new EloquentModelStub; - $model->setVisible(['name']); - $model->name = 'Taylor'; - $model->age = 26; - $array = $model->toArray(); - - $this->assertEquals(['name' => 'Taylor'], $array); - } - - - public function testHiddenCanAlsoExcludeRelationships(): void - { - $model = new EloquentModelStub; - $model->name = 'Taylor'; - $model->setRelation('foo', ['bar']); - $model->setHidden(['foo', 'list_items', 'password']); - $array = $model->toArray(); - - $this->assertEquals(['name' => 'Taylor'], $array); - } - - - public function testToArraySnakeAttributes(): void - { - $model = new EloquentModelStub; - $model->setRelation('namesList', new Illuminate\Database\Eloquent\Collection([ - new EloquentModelStub(['bar' => 'baz']), new EloquentModelStub(['bam' => 'boom']) - ])); - $array = $model->toArray(); - - $this->assertEquals('baz', $array['names_list'][0]['bar']); - $this->assertEquals('boom', $array['names_list'][1]['bam']); - - $model = new EloquentModelCamelStub; - $model->setRelation('namesList', new Illuminate\Database\Eloquent\Collection([ - new EloquentModelStub(['bar' => 'baz']), new EloquentModelStub(['bam' => 'boom']) - ])); - $array = $model->toArray(); - - $this->assertEquals('baz', $array['namesList'][0]['bar']); - $this->assertEquals('boom', $array['namesList'][1]['bam']); - } - - - public function testToArrayUsesMutators(): void - { - $model = new EloquentModelStub; - $model->list_items = [1, 2, 3]; - $array = $model->toArray(); - - $this->assertEquals([1, 2, 3], $array['list_items']); - } - - - public function testFillable(): void - { - $model = new EloquentModelStub; - $model->fillable(['name', 'age']); - $model->fill(['name' => 'foo', 'age' => 'bar']); - $this->assertEquals('foo', $model->name); - $this->assertEquals('bar', $model->age); - } - - - public function testUnguardAllowsAnythingToBeSet(): void - { - $model = new EloquentModelStub; - EloquentModelStub::unguard(); - $model->guard(['*']); - $model->fill(['name' => 'foo', 'age' => 'bar']); - $this->assertEquals('foo', $model->name); - $this->assertEquals('bar', $model->age); - EloquentModelStub::setUnguardState(false); - } - - - public function testUnderscorePropertiesAreNotFilled(): void - { - $model = new EloquentModelStub; - $model->fill(['_method' => 'PUT']); - $this->assertEquals([], $model->getAttributes()); - } - - - public function testGuarded(): void - { - $model = new EloquentModelStub; - $model->guard(['name', 'age']); - $model->fill(['name' => 'foo', 'age' => 'bar', 'foo' => 'bar']); - $this->assertFalse(isset($model->name)); - $this->assertFalse(isset($model->age)); - $this->assertEquals('bar', $model->foo); - } - - - public function testFillableOverridesGuarded(): void - { - $model = new EloquentModelStub; - $model->guard(['name', 'age']); - $model->fillable(['age', 'foo']); - $model->fill(['name' => 'foo', 'age' => 'bar', 'foo' => 'bar']); - $this->assertFalse(isset($model->name)); - $this->assertEquals('bar', $model->age); - $this->assertEquals('bar', $model->foo); - } - - - public function testGlobalGuarded(): void - { - $this->expectException(Illuminate\Database\Eloquent\MassAssignmentException::class); - $model = new EloquentModelStub; - $model->guard(['*']); - $model->fill(['name' => 'foo', 'age' => 'bar', 'votes' => 'baz']); - } - - - public function testHasOneCreatesProperRelation(): void - { - $model = new EloquentModelStub; - $this->addMockConnection($model); - $relation = $model->hasOne('EloquentModelSaveStub'); - $this->assertEquals('save_stub.eloquent_model_stub_id', $relation->getForeignKey()); - - $model = new EloquentModelStub; - $this->addMockConnection($model); - $relation = $model->hasOne('EloquentModelSaveStub', 'foo'); - $this->assertEquals('save_stub.foo', $relation->getForeignKey()); - $this->assertSame($model, $relation->getParent()); - $this->assertInstanceOf('EloquentModelSaveStub', $relation->getQuery()->getModel()); - } - - - public function testMorphOneCreatesProperRelation(): void - { - $model = new EloquentModelStub; - $this->addMockConnection($model); - $relation = $model->morphOne('EloquentModelSaveStub', 'morph'); - $this->assertEquals('save_stub.morph_id', $relation->getForeignKey()); - $this->assertEquals('save_stub.morph_type', $relation->getMorphType()); - $this->assertEquals('EloquentModelStub', $relation->getMorphClass()); - } - - - public function testHasManyCreatesProperRelation(): void - { - $model = new EloquentModelStub; - $this->addMockConnection($model); - $relation = $model->hasMany('EloquentModelSaveStub'); - $this->assertEquals('save_stub.eloquent_model_stub_id', $relation->getForeignKey()); - - $model = new EloquentModelStub; - $this->addMockConnection($model); - $relation = $model->hasMany('EloquentModelSaveStub', 'foo'); - $this->assertEquals('save_stub.foo', $relation->getForeignKey()); - $this->assertSame($model, $relation->getParent()); - $this->assertInstanceOf('EloquentModelSaveStub', $relation->getQuery()->getModel()); - } - - - public function testMorphManyCreatesProperRelation(): void - { - $model = new EloquentModelStub; - $this->addMockConnection($model); - $relation = $model->morphMany('EloquentModelSaveStub', 'morph'); - $this->assertEquals('save_stub.morph_id', $relation->getForeignKey()); - $this->assertEquals('save_stub.morph_type', $relation->getMorphType()); - $this->assertEquals('EloquentModelStub', $relation->getMorphClass()); - } - - - public function testBelongsToCreatesProperRelation(): void - { - $model = new EloquentModelStub; - $this->addMockConnection($model); - $relation = $model->belongsToStub(); - $this->assertEquals('belongs_to_stub_id', $relation->getForeignKey()); - $this->assertSame($model, $relation->getParent()); - $this->assertInstanceOf('EloquentModelSaveStub', $relation->getQuery()->getModel()); - - $model = new EloquentModelStub; - $this->addMockConnection($model); - $relation = $model->belongsToExplicitKeyStub(); - $this->assertEquals('foo', $relation->getForeignKey()); - } - - - public function testMorphToCreatesProperRelation(): void - { - $model = new EloquentModelStub; - $this->addMockConnection($model); - $relation = $model->morphToStub(); - $this->assertEquals('morph_to_stub_id', $relation->getForeignKey()); - $this->assertSame($model, $relation->getParent()); - $this->assertInstanceOf('EloquentModelSaveStub', $relation->getQuery()->getModel()); - } - - - public function testBelongsToManyCreatesProperRelation(): void - { - $model = new EloquentModelStub; - $this->addMockConnection($model); - $relation = $model->belongsToMany('EloquentModelSaveStub'); - $this->assertEquals('eloquent_model_save_stub_eloquent_model_stub.eloquent_model_stub_id', $relation->getForeignKey()); - $this->assertEquals('eloquent_model_save_stub_eloquent_model_stub.eloquent_model_save_stub_id', $relation->getOtherKey()); - $this->assertSame($model, $relation->getParent()); - $this->assertInstanceOf('EloquentModelSaveStub', $relation->getQuery()->getModel()); - $this->assertEquals(__FUNCTION__, $relation->getRelationName()); - - $model = new EloquentModelStub; - $this->addMockConnection($model); - $relation = $model->belongsToMany('EloquentModelSaveStub', 'table', 'foreign', 'other'); - $this->assertEquals('table.foreign', $relation->getForeignKey()); - $this->assertEquals('table.other', $relation->getOtherKey()); - $this->assertSame($model, $relation->getParent()); - $this->assertInstanceOf('EloquentModelSaveStub', $relation->getQuery()->getModel()); - } - - - public function testModelsAssumeTheirName(): void - { - $model = new EloquentModelWithoutTableStub; - $this->assertEquals('eloquent_model_without_table_stubs', $model->getTable()); - - require_once __DIR__.'/stubs/EloquentModelNamespacedStub.php'; - $namespacedModel = new Foo\Bar\EloquentModelNamespacedStub; - $this->assertEquals('eloquent_model_namespaced_stubs', $namespacedModel->getTable()); - } - - - public function testTheMutatorCacheIsPopulated(): void - { - $class = new EloquentModelStub; - - $expectedAttributes = [ - 'list_items', - 'password', - 'appendable' - ]; - - $this->assertEquals($expectedAttributes, $class->getMutatedAttributes()); - } - - - public function testCloneModelMakesAFreshCopyOfTheModel(): void - { - $class = new EloquentModelStub; - $class->id = 1; - $class->exists = true; - $class->first = 'taylor'; - $class->last = 'otwell'; - $class->created_at = $class->freshTimestamp(); - $class->updated_at = $class->freshTimestamp(); - $class->setRelation('foo', ['bar']); - - $clone = $class->replicate(); - - $this->assertNull($clone->id); - $this->assertFalse($clone->exists); - $this->assertEquals('taylor', $clone->first); - $this->assertEquals('otwell', $clone->last); - $this->assertObjectNotHasProperty('created_at', $clone); - $this->assertObjectNotHasProperty('updated_at', $clone); - $this->assertEquals(['bar'], $clone->foo); - } - - - public function testModelObserversCanBeAttachedToModels(): void - { - EloquentModelStub::setEventDispatcher($events = m::mock(Dispatcher::class)); - $events->shouldReceive('listen')->once()->with('eloquent.creating: EloquentModelStub', 'EloquentTestObserverStub@creating'); - $events->shouldReceive('listen')->once()->with('eloquent.saved: EloquentModelStub', 'EloquentTestObserverStub@saved'); - $events->shouldReceive('forget'); - EloquentModelStub::observe(new EloquentTestObserverStub); - EloquentModelStub::flushEventListeners(); - } - - - public function testSetObservableEvents(): void - { - $class = new EloquentModelStub; - $class->setObservableEvents(['foo']); - - $this->assertContains('foo', $class->getObservableEvents()); - } - - - public function testAddObservableEvent(): void - { - $class = new EloquentModelStub; - $class->addObservableEvents('foo'); - - $this->assertContains('foo', $class->getObservableEvents()); - } - - public function testAddMultipleObserveableEvents(): void - { - $class = new EloquentModelStub; - $class->addObservableEvents('foo', 'bar'); - - $this->assertContains('foo', $class->getObservableEvents()); - $this->assertContains('bar', $class->getObservableEvents()); - } - - - public function testRemoveObservableEvent(): void - { - $class = new EloquentModelStub; - $class->setObservableEvents(['foo', 'bar']); - $class->removeObservableEvents('bar'); - - $this->assertNotContains('bar', $class->getObservableEvents()); - } - - public function testRemoveMultipleObservableEvents(): void - { - $class = new EloquentModelStub; - $class->setObservableEvents(['foo', 'bar']); - $class->removeObservableEvents('foo', 'bar'); - - $this->assertNotContains('foo', $class->getObservableEvents()); - $this->assertNotContains('bar', $class->getObservableEvents()); - } - - - public function testGetModelAttributeMethodThrowsExceptionIfNotRelation(): void - { - $this->expectException(LogicException::class); - $model = new EloquentModelStub; - $relation = $model->incorrect_relation_stub; - } - - - public function testModelIsBootedOnUnserialize(): void - { - $model = new EloquentModelBootingTestStub; - $this->assertTrue(EloquentModelBootingTestStub::isBooted()); - $model->foo = 'bar'; - $string = serialize($model); - $model = null; - EloquentModelBootingTestStub::unboot(); - $this->assertFalse(EloquentModelBootingTestStub::isBooted()); - $model = unserialize($string); - $this->assertTrue(EloquentModelBootingTestStub::isBooted()); - } - - - public function testAppendingOfAttributes(): void - { - $model = new EloquentModelAppendsStub; - - $this->assertTrue(isset($model->is_admin)); - $this->assertTrue(isset($model->camelCased)); - $this->assertTrue(isset($model->StudlyCased)); - - $this->assertEquals('admin', $model->is_admin); - $this->assertEquals('camelCased', $model->camelCased); - $this->assertEquals('StudlyCased', $model->StudlyCased); - - $model->setHidden(['is_admin', 'camelCased', 'StudlyCased']); - $this->assertEquals([], $model->toArray()); - - $model->setVisible([]); - $this->assertEquals([], $model->toArray()); - } - - - public function testReplicateCreatesANewModelInstanceWithSameAttributeValues(): void - { - $model = new EloquentModelStub; - $model->id = 'id'; - $model->foo = 'bar'; - $model->created_at = new DateTime; - $model->updated_at = new DateTime; - $replicated = $model->replicate(); - - $this->assertNull($replicated->id); - $this->assertEquals('bar', $replicated->foo); - $this->assertNull($replicated->created_at); - $this->assertNull($replicated->updated_at); - } - - - public function testIncrementOnExistingModelCallsQueryAndSetsAttribute(): void - { - $model = m::mock('EloquentModelStub[newQuery]'); - $model->exists = true; - $model->id = 1; - $model->syncOriginalAttribute('id'); - $model->foo = 2; - - $model->allows()->newQuery()->andReturn($query = m::mock(Builder::class)); - $query->allows()->where()->withAnyArgs()->andReturn($query); - $query->allows()->increment()->withAnyArgs()->andReturn(1); - - $model->publicIncrement('foo'); - - $this->assertEquals(3, $model->foo); - $this->assertFalse($model->isDirty()); - } - - public function testRelationshipTouchOwnersIsPropagated(): void - { - $relation = $this->getMockBuilder(BelongsTo::class)->onlyMethods(['touch'])->disableOriginalConstructor()->getMock(); - $relation->expects($this->once())->method('touch'); - - $model = m::mock('EloquentModelStub[partner]'); - $this->addMockConnection($model); - $model->shouldReceive('partner')->once()->andReturn($relation); - $model->setTouchedRelations(['partner']); - - $mockPartnerModel = m::mock('EloquentModelStub[touchOwners]'); - $mockPartnerModel->shouldReceive('touchOwners')->once(); - $model->setRelation('partner', $mockPartnerModel); - - $model->touchOwners(); - } - - - public function testRelationshipTouchOwnersIsNotPropagatedIfNoRelationshipResult(): void - { - $relation = $this->getMockBuilder(BelongsTo::class)->onlyMethods(['touch'])->disableOriginalConstructor()->getMock(); - $relation->expects($this->once())->method('touch'); - - $model = m::mock('EloquentModelStub[partner]'); - $this->addMockConnection($model); - $model->shouldReceive('partner')->once()->andReturn($relation); - $model->setTouchedRelations(['partner']); - - $model->setRelation('partner', null); - - $model->touchOwners(); - } - - - public function testTimestampsAreNotUpdatedWithTimestampsFalseSaveOption(): void - { - $model = m::mock('EloquentModelStub[newQueryWithoutScopes]'); - $query = m::mock(Builder::class); - $query->shouldReceive('where')->once()->with('id', '=', 1); - $query->shouldReceive('update')->once()->with(['name' => 'taylor']); - $model->shouldReceive('newQueryWithoutScopes')->once()->andReturn($query); - - $model->id = 1; - $model->syncOriginal(); - $model->name = 'taylor'; - $model->exists = true; - $this->assertTrue($model->save(['timestamps' => false])); - $this->assertNull($model->updated_at); - } - - - protected function addMockConnection($model): void - { - $model->setConnectionResolver($resolver = m::mock(ConnectionResolverInterface::class)); - $resolver->shouldReceive('connection')->andReturn(m::mock(Connection::class)); - $model->getConnection()->shouldReceive('getQueryGrammar')->andReturn(m::mock( - Grammar::class - )); - $model->getConnection()->shouldReceive('getPostProcessor')->andReturn(m::mock( - Processor::class - )); - } - -} - -class EloquentTestObserverStub { - public function creating(): void - {} - public function saved(): void - {} -} - -class EloquentModelStub extends Illuminate\Database\Eloquent\Model { - protected string $table = 'stub'; - protected array $guarded = []; - protected string $morph_to_stub_type = 'EloquentModelSaveStub'; - public function getListItemsAttribute($value) - { - return json_decode((string) $value, true); - } - public function setListItemsAttribute($value): void - { - $this->attributes['list_items'] = json_encode($value); - } - public function getPasswordAttribute(): string - { - return '******'; - } - public function setPasswordAttribute($value): void - { - $this->attributes['password_hash'] = md5((string) $value); - } - public function publicIncrement($column, $amount = 1): int - { - return $this->increment($column, $amount); - } - public function belongsToStub(): BelongsTo - { - return $this->belongsTo('EloquentModelSaveStub'); - } - public function morphToStub(): \Illuminate\Database\Eloquent\Relations\MorphTo - { - return $this->morphTo(); - } - public function belongsToExplicitKeyStub(): BelongsTo - { - return $this->belongsTo('EloquentModelSaveStub', 'foo'); - } - public function incorrectRelationStub(): string - { - return 'foo'; - } - #[\Override] - public function getDates(): array - { - return []; - } - public function getAppendableAttribute(): string - { - return 'appended'; - } -} - -class EloquentModelCamelStub extends EloquentModelStub { - public static bool $snakeAttributes = false; -} - -class EloquentDateModelStub extends EloquentModelStub { - #[\Override] - public function getDates(): array - { - return ['created_at', 'updated_at']; - } -} - -class EloquentModelSaveStub extends Illuminate\Database\Eloquent\Model { - protected string $table = 'save_stub'; - protected array $guarded = []; - #[\Override] - public function save(array $options = []): bool { $_SERVER['__eloquent.saved'] = true; return true; } - #[\Override] - public function setIncrementing($value): void - { - $this->incrementing = $value; - } -} - -class EloquentModelFindStub extends Illuminate\Database\Eloquent\Model { - #[\Override] - public function newQuery() - { - $mock = m::mock(Builder::class); - $mock->shouldReceive('find')->once()->with(1, ['*'])->andReturn('foo'); - return $mock; - } -} - -class EloquentModelFindWithWritePdoStub extends Illuminate\Database\Eloquent\Model { - #[\Override] - public function newQuery() - { - $mock = m::mock(Builder::class); - $mock->expects('useWritePdo')->andReturnSelf(); - $mock->expects('find')->with(1)->andReturns('foo'); - - return $mock; - } -} - -class EloquentModelFindNotFoundStub extends Illuminate\Database\Eloquent\Model { - #[\Override] - public function newQuery() - { - $mock = m::mock(Builder::class); - $mock->shouldReceive('find')->once()->with(1, ['*'])->andReturn(null); - return $mock; - } -} - -class EloquentModelDestroyStub extends Illuminate\Database\Eloquent\Model { - #[\Override] - public function newQuery() - { - $mock = m::mock(Builder::class); - $mock->shouldReceive('whereIn')->once()->with('id', [1, 2, 3])->andReturn($mock); - $mock->shouldReceive('get')->once()->andReturn([$model = m::mock('StdClass')]); - $model->shouldReceive('delete')->once(); - return $mock; - } -} - -class EloquentModelHydrateRawStub extends Illuminate\Database\Eloquent\Model { - #[\Override] - public static function hydrate(array $items, $connection = null): Collection { return new Collection(['hydrated']); } - #[\Override] - public function getConnection(): Connection - { - $mock = m::mock(Connection::class); - $mock->shouldReceive('select')->once()->with('SELECT ?', ['foo'])->andReturn([]); - return $mock; - } -} - -class EloquentModelFindManyStub extends Illuminate\Database\Eloquent\Model { - #[\Override] - public function newQuery() - { - $mock = m::mock(Builder::class); - $mock->shouldReceive('find')->once()->with([1, 2], ['*'])->andReturn('foo'); - return $mock; - } -} - -class EloquentModelWithStub extends Illuminate\Database\Eloquent\Model { - #[\Override] - public function newQuery() - { - $mock = m::mock(Builder::class); - $mock->shouldReceive('with')->once()->with(['foo', 'bar'])->andReturn('foo'); - return $mock; - } -} - -class EloquentModelWithoutTableStub extends Illuminate\Database\Eloquent\Model {} - -class EloquentModelBootingTestStub extends Illuminate\Database\Eloquent\Model { - public static function unboot(): void - { - unset(static::$booted[static::class]); - } - public static function isBooted(): bool - { - return array_key_exists(static::class, static::$booted); - } -} - -class EloquentModelAppendsStub extends Illuminate\Database\Eloquent\Model { - protected array $appends = ['is_admin', 'camelCased', 'StudlyCased']; - public function getIsAdminAttribute(): string - { - return 'admin'; - } - public function getCamelCasedAttribute(): string - { - return 'camelCased'; - } - public function getStudlyCasedAttribute(): string - { - return 'StudlyCased'; - } -} diff --git a/tests/Database/DatabaseEloquentMorphTest.php b/tests/Database/DatabaseEloquentMorphTest.php deleted file mode 100755 index a34492bd2..000000000 --- a/tests/Database/DatabaseEloquentMorphTest.php +++ /dev/null @@ -1,120 +0,0 @@ -getOneRelation(); - } - - - public function testMorphOneEagerConstraintsAreProperlyAdded() - { - $relation = $this->getOneRelation(); - $relation->getQuery()->shouldReceive('whereIn')->once()->with('table.morph_id', [1, 2]); - $relation->getQuery()->shouldReceive('where')->once()->with('table.morph_type', get_class($relation->getParent())); - - $model1 = new EloquentMorphResetModelStub; - $model1->id = 1; - $model2 = new EloquentMorphResetModelStub; - $model2->id = 2; - $relation->addEagerConstraints([$model1, $model2]); - } - - - /** - * Note that the tests are the exact same for morph many because the classes share this code... - * Will still test to be safe. - */ - public function testMorphManySetsProperConstraints() - { - $relation = $this->getManyRelation(); - } - - - public function testMorphManyEagerConstraintsAreProperlyAdded() - { - $relation = $this->getManyRelation(); - $relation->getQuery()->shouldReceive('whereIn')->once()->with('table.morph_id', [1, 2]); - $relation->getQuery()->shouldReceive('where')->once()->with('table.morph_type', get_class($relation->getParent())); - - $model1 = new EloquentMorphResetModelStub; - $model1->id = 1; - $model2 = new EloquentMorphResetModelStub; - $model2->id = 2; - $relation->addEagerConstraints([$model1, $model2]); - } - - - public function testCreateFunctionOnMorph() - { - // Doesn't matter which relation type we use since they share the code... - $relation = $this->getOneRelation(); - $created = m::mock(Model::class); - $created->shouldReceive('setAttribute')->once()->with('morph_id', 1); - $created->shouldReceive('setAttribute')->once()->with('morph_type', get_class($relation->getParent())); - $relation->getRelated()->shouldReceive('newInstance')->once()->with(['name' => 'taylor'])->andReturn($created); - $created->shouldReceive('save')->once()->andReturn(true); - - $this->assertEquals($created, $relation->create(['name' => 'taylor'])); - } - - - protected function getOneRelation() - { - $builder = m::mock(Builder::class); - $builder->shouldReceive('where')->once()->with('table.morph_id', '=', 1); - $related = m::mock(Model::class); - $builder->shouldReceive('getModel')->andReturn($related); - $parent = m::mock(Model::class); - $parent->shouldReceive('getAttribute')->with('id')->andReturn(1); - $parent->shouldReceive('getMorphClass')->andReturn(get_class($parent)); - $builder->shouldReceive('where')->once()->with('table.morph_type', get_class($parent)); - return new MorphOne($builder, $parent, 'table.morph_type', 'table.morph_id', 'id'); - } - - - protected function getManyRelation() - { - $builder = m::mock(Builder::class); - $builder->shouldReceive('where')->once()->with('table.morph_id', '=', 1); - $related = m::mock(Model::class); - $builder->shouldReceive('getModel')->andReturn($related); - $parent = m::mock(Model::class); - $parent->shouldReceive('getAttribute')->with('id')->andReturn(1); - $parent->shouldReceive('getMorphClass')->andReturn(get_class($parent)); - $builder->shouldReceive('where')->once()->with('table.morph_type', get_class($parent)); - return new MorphMany($builder, $parent, 'table.morph_type', 'table.morph_id', 'id'); - } - -} - - -class EloquentMorphResetModelStub extends Illuminate\Database\Eloquent\Model {} - - -class EloquentMorphResetBuilderStub extends Illuminate\Database\Eloquent\Builder { - public function __construct() { $this->query = new EloquentRelationQueryStub; } - #[\Override] - public function getModel() { return new EloquentMorphResetModelStub; } - public function isSoftDeleting() { return false; } -} - - -class EloquentMorphQueryStub extends Illuminate\Database\Query\Builder { - public function __construct() {} -} diff --git a/tests/Database/DatabaseEloquentMorphToManyTest.php b/tests/Database/DatabaseEloquentMorphToManyTest.php deleted file mode 100644 index 0f925721c..000000000 --- a/tests/Database/DatabaseEloquentMorphToManyTest.php +++ /dev/null @@ -1,120 +0,0 @@ -getRelation(); - $relation->getQuery()->shouldReceive('whereIn')->once()->with('taggables.taggable_id', [1, 2]); - $relation->getQuery()->shouldReceive('where')->once()->with( - 'taggables.taggable_type', - get_class($relation->getParent()) - ); - $model1 = new EloquentMorphToManyModelStub; - $model1->id = 1; - $model2 = new EloquentMorphToManyModelStub; - $model2->id = 2; - $relation->addEagerConstraints([$model1, $model2]); - } - - - public function testAttachInsertsPivotTableRecord(): void - { - $relation = $this->getMock(MorphToMany::class, ['touchIfTouching'], $this->getRelationArguments()); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('taggables')->andReturn($query); - $query->shouldReceive('insert')->once()->with( - [['taggable_id' => 1, 'taggable_type' => get_class($relation->getParent()), 'tag_id' => 2, 'foo' => 'bar']] - )->andReturn(true); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $relation->expects($this->once())->method('touchIfTouching'); - - $relation->attach(2, ['foo' => 'bar']); - } - - - public function testDetachRemovesPivotTableRecord(): void - { - $relation = $this->getMock(MorphToMany::class, ['touchIfTouching'], $this->getRelationArguments()); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('taggables')->andReturn($query); - $query->shouldReceive('where')->once()->with('taggable_id', 1)->andReturn($query); - $query->shouldReceive('where')->once()->with('taggable_type', get_class($relation->getParent()))->andReturn($query); - $query->shouldReceive('whereIn')->once()->with('tag_id', [1, 2, 3]); - $query->shouldReceive('delete')->once()->andReturn(true); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $relation->expects($this->once())->method('touchIfTouching'); - - $this->assertTrue($relation->detach([1, 2, 3])); - } - - - public function testDetachMethodClearsAllPivotRecordsWhenNoIDsAreGiven(): void - { - $relation = $this->getMock(MorphToMany::class, ['touchIfTouching'], $this->getRelationArguments()); - $query = m::mock('stdClass'); - $query->shouldReceive('from')->once()->with('taggables')->andReturn($query); - $query->shouldReceive('where')->once()->with('taggable_id', 1)->andReturn($query); - $query->shouldReceive('where')->once()->with('taggable_type', get_class($relation->getParent()))->andReturn($query); - $query->shouldReceive('whereIn')->never(); - $query->shouldReceive('delete')->once()->andReturn(true); - $relation->getQuery()->shouldReceive('getQuery')->andReturn($mockQueryBuilder = m::mock('StdClass')); - $mockQueryBuilder->shouldReceive('newQuery')->once()->andReturn($query); - $relation->expects($this->once())->method('touchIfTouching'); - - $this->assertTrue($relation->detach()); - } - - - public function getRelation(): MorphToMany - { - [$builder, $parent] = $this->getRelationArguments(); - - return new MorphToMany($builder, $parent, 'taggable', 'taggables', 'taggable_id', 'tag_id'); - } - - - public function getRelationArguments():array - { - $parent = m::mock(Model::class); - $parent->shouldReceive('getMorphClass')->andReturn(get_class($parent)); - $parent->shouldReceive('getKey')->andReturn(1); - $parent->shouldReceive('getCreatedAtColumn')->andReturn('created_at'); - $parent->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at'); - $parent->shouldReceive('getMorphClass')->andReturn(get_class($parent)); - - $builder = m::mock(Builder::class); - $related = m::mock(Model::class); - $builder->shouldReceive('getModel')->andReturn($related); - - $related->shouldReceive('getTable')->andReturn('tags'); - $related->shouldReceive('getKeyName')->andReturn('id'); - $related->shouldReceive('getMorphClass')->andReturn(get_class($related)); - - $builder->shouldReceive('join')->once()->with('taggables', 'tags.id', '=', 'taggables.tag_id'); - $builder->shouldReceive('where')->once()->with('taggables.taggable_id', '=', 1); - $builder->shouldReceive('where')->once()->with('taggables.taggable_type', get_class($parent)); - - return [$builder, $parent, 'taggable', 'taggables', 'taggable_id', 'tag_id', 'relation_name', false]; - } - -} - -class EloquentMorphToManyModelStub extends Illuminate\Database\Eloquent\Model { - protected array $guarded = []; -} diff --git a/tests/Database/DatabaseEloquentMorphToTest.php b/tests/Database/DatabaseEloquentMorphToTest.php deleted file mode 100644 index 07538756e..000000000 --- a/tests/Database/DatabaseEloquentMorphToTest.php +++ /dev/null @@ -1,155 +0,0 @@ -getRelation(); - $relation->addEagerConstraints( - [ - $one = (object)['morph_type' => 'morph_type_1', 'foreign_key' => 'foreign_key_1'], - $two = (object) ['morph_type' => 'morph_type_1', 'foreign_key' => 'foreign_key_1'], - $three = (object) ['morph_type' => 'morph_type_2', 'foreign_key' => 'foreign_key_2'], - ] - ); - - $dictionary = $relation->getDictionary(); - - $this->assertEquals([ - 'morph_type_1' => [ - 'foreign_key_1' => [ - $one, - $two - ] - ], - 'morph_type_2' => [ - 'foreign_key_2' => [ - $three - ] - ], - ], $dictionary); - } - - - public function testModelsAreProperlyPulledAndMatched() - { - $relation = $this->getRelation(); - - $one = m::mock('StdClass'); - $one->morph_type = 'morph_type_1'; - $one->foreign_key = 'foreign_key_1'; - - $two = m::mock('StdClass'); - $two->morph_type = 'morph_type_1'; - $two->foreign_key = 'foreign_key_1'; - - $three = m::mock('StdClass'); - $three->morph_type = 'morph_type_2'; - $three->foreign_key = 'foreign_key_2'; - - $relation->addEagerConstraints([$one, $two, $three]); - - $relation->shouldReceive('createModelByType')->once()->with('morph_type_1')->andReturn($firstQuery = m::mock( - Builder::class - )); - $relation->shouldReceive('createModelByType')->once()->with('morph_type_2')->andReturn($secondQuery = m::mock( - Builder::class - )); - $firstQuery->shouldReceive('getKeyName')->andReturn('id'); - $secondQuery->shouldReceive('getKeyName')->andReturn('id'); - - $firstQuery->shouldReceive('newQuery')->once()->andReturn($firstQuery); - $secondQuery->shouldReceive('newQuery')->once()->andReturn($secondQuery); - - $firstQuery->shouldReceive('whereIn')->once()->with('id', ['foreign_key_1'])->andReturn($firstQuery); - $firstQuery->shouldReceive('get')->once()->andReturn(Collection::make([$resultOne = m::mock('StdClass')])); - $resultOne->shouldReceive('getKey')->andReturn('foreign_key_1'); - - $secondQuery->shouldReceive('whereIn')->once()->with('id', ['foreign_key_2'])->andReturn($secondQuery); - $secondQuery->shouldReceive('get')->once()->andReturn(Collection::make([$resultTwo = m::mock('StdClass')])); - $resultTwo->shouldReceive('getKey')->andReturn('foreign_key_2'); - - $one->shouldReceive('setRelation')->once()->with('relation', $resultOne); - $two->shouldReceive('setRelation')->once()->with('relation', $resultOne); - $three->shouldReceive('setRelation')->once()->with('relation', $resultTwo); - - $relation->getEager(); - } - - public function testModelsWithSoftDeleteAreProperlyPulled() - { - $builder = m::mock(Builder::class); - - $relation = $this->getRelation(null, $builder); - - $builder->shouldReceive('getMacro')->once()->with('withTrashed')->andReturn(function() { return true; }); - $builder->shouldReceive('withTrashed')->once(); - - $relation->withTrashed(); - } - - public function testAssociateMethodSetsForeignKeyAndTypeOnModel() - { - $parent = m::mock(Model::class); - $parent->shouldReceive('getAttribute')->once()->with('foreign_key')->andReturn('foreign.value'); - - $relation = $this->getRelationAssociate($parent); - - $associate = m::mock(Model::class); - $associate->shouldReceive('getKey')->once()->andReturn(1); - $associate->shouldReceive('getMorphClass')->once()->andReturn('Model'); - - $parent->shouldReceive('setAttribute')->once()->with('foreign_key', 1); - $parent->shouldReceive('setAttribute')->once()->with('morph_type', 'Model'); - $parent->shouldReceive('setRelation')->once()->with('relation', $associate); - - $relation->associate($associate); - } - - - protected function getRelationAssociate($parent) - { - $builder = m::mock(Builder::class); - $builder->shouldReceive('where')->with('relation.id', '=', 'foreign.value'); - $related = m::mock(Model::class); - $related->shouldReceive('getKey')->andReturn(1); - $related->shouldReceive('getTable')->andReturn('relation'); - $builder->shouldReceive('getModel')->andReturn($related); - return new MorphTo($builder, $parent, 'foreign_key', 'id', 'morph_type', 'relation'); - } - - - public function getRelation($parent = null, $builder = null) - { - $builder = $builder ?: m::mock(Builder::class); - $builder->shouldReceive('where')->with('relation.id', '=', 'foreign.value'); - $related = m::mock(Model::class); - $related->shouldReceive('getKeyName')->andReturn('id'); - $related->shouldReceive('getTable')->andReturn('relation'); - $builder->shouldReceive('getModel')->andReturn($related); - $parent = $parent ?: new EloquentMorphToModelStub; - $morphTo = m::mock('Illuminate\Database\Eloquent\Relations\MorphTo[createModelByType]', [$builder, $parent, 'foreign_key', 'id', 'morph_type', 'relation'] - ); - return $morphTo; - } - -} - - -class EloquentMorphToModelStub extends Illuminate\Database\Eloquent\Model { - public $foreign_key = 'foreign.value'; -} diff --git a/tests/Database/DatabaseEloquentPivotTest.php b/tests/Database/DatabaseEloquentPivotTest.php deleted file mode 100755 index b7b7f6df5..000000000 --- a/tests/Database/DatabaseEloquentPivotTest.php +++ /dev/null @@ -1,104 +0,0 @@ -shouldReceive('getConnectionName')->once()->andReturn('connection'); - $pivot = new Pivot($parent, ['foo' => 'bar'], 'table', true); - - $this->assertEquals(['foo' => 'bar'], $pivot->getAttributes()); - $this->assertEquals('connection', $pivot->getConnectionName()); - $this->assertEquals('table', $pivot->getTable()); - $this->assertTrue($pivot->exists); - } - - - public function testPropertiesUnchangedAreNotDirty(): void - { - $parent = m::mock('Illuminate\Database\Eloquent\Model[getConnectionName]'); - $parent->shouldReceive('getConnectionName')->once()->andReturn('connection'); - $pivot = new Pivot($parent, ['foo' => 'bar', 'shimy' => 'shake'], 'table', true); - - $this->assertEquals([], $pivot->getDirty()); - } - - - public function testPropertiesChangedAreDirty(): void - { - $parent = m::mock('Illuminate\Database\Eloquent\Model[getConnectionName]'); - $parent->shouldReceive('getConnectionName')->once()->andReturn('connection'); - $pivot = new Pivot($parent, ['foo' => 'bar', 'shimy' => 'shake'], 'table', true); - $pivot->shimy = 'changed'; - - $this->assertEquals(['shimy' => 'changed'], $pivot->getDirty()); - } - - - public function testTimestampPropertyIsSetIfCreatedAtInAttributes(): void - { - $parent = m::mock('Illuminate\Database\Eloquent\Model[getConnectionName,getDates]'); - $parent->shouldReceive('getConnectionName')->andReturn('connection'); - $parent->shouldReceive('getDates')->andReturn([]); - $pivot = new DatabaseEloquentPivotTestDateStub($parent, ['foo' => 'bar', 'created_at' => 'foo'], 'table'); - $this->assertTrue($pivot->timestamps); - - $pivot = new DatabaseEloquentPivotTestDateStub($parent, ['foo' => 'bar'], 'table'); - $this->assertFalse($pivot->timestamps); - } - - - public function testKeysCanBeSetProperly(): void - { - $parent = m::mock('Illuminate\Database\Eloquent\Model[getConnectionName]'); - $parent->shouldReceive('getConnectionName')->once()->andReturn('connection'); - $pivot = new Pivot($parent, ['foo' => 'bar'], 'table'); - $pivot->setPivotKeys('foreign', 'other'); - - $this->assertEquals('foreign', $pivot->getForeignKey()); - $this->assertEquals('other', $pivot->getOtherKey()); - } - - - public function testDeleteMethodDeletesModelByKeys(): void - { - $parent = m::mock('Illuminate\Database\Eloquent\Model[getConnectionName]'); - $parent->guard([]); - $parent->shouldReceive('getConnectionName')->once()->andReturn('connection'); - $pivot = $this->getMock(Pivot::class, ['newQuery'], [$parent, ['foo' => 'bar'], 'table']); - $pivot->setPivotKeys('foreign', 'other'); - $pivot->foreign = 'foreign.value'; - $pivot->other = 'other.value'; - $query = m::mock('stdClass'); - $query->shouldReceive('where')->once()->with('foreign', 'foreign.value')->andReturn($query); - $query->shouldReceive('where')->once()->with('other', 'other.value')->andReturn($query); - $query->shouldReceive('delete')->once()->andReturn(true); - $pivot->expects($this->once())->method('newQuery')->willReturn($query); - - $this->assertTrue($pivot->delete()); - } - -} - - -class DatabaseEloquentPivotTestModelStub extends Illuminate\Database\Eloquent\Model {} - -class DatabaseEloquentPivotTestDateStub extends Illuminate\Database\Eloquent\Relations\Pivot { - #[\Override] - public function getDates(): array - { - return []; - } -} diff --git a/tests/Database/DatabaseEloquentRelationTest.php b/tests/Database/DatabaseEloquentRelationTest.php deleted file mode 100755 index dfbdcea11..000000000 --- a/tests/Database/DatabaseEloquentRelationTest.php +++ /dev/null @@ -1,118 +0,0 @@ -setRelation('test', $relation); - $parent->setRelation('foo','bar'); - $this->assertTrue(!array_key_exists('foo', $parent->toArray())); - } - - - public function testTouchMethodUpdatesRelatedTimestamps() - { - $builder = m::mock(\Illuminate\Database\Eloquent\Builder::class); - $parent = m::mock(Model::class); - $parent->shouldReceive('getAttribute')->with('id')->andReturn(1); - $builder->shouldReceive('getModel')->andReturn($related = m::mock('StdClass')); - $builder->shouldReceive('where'); - $relation = new HasOne($builder, $parent, 'foreign_key', 'id'); - $related->shouldReceive('getTable')->andReturn('table'); - $related->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at'); - $related->shouldReceive('freshTimestampString')->andReturn(Carbon::now()); - $builder->shouldReceive('update')->once()->with(['updated_at' => Carbon::now()]); - - $relation->touch(); - } - - /** - * Testing to ensure loop does not occur during relational queries in global scopes - * - * Executing parent model's global scopes could result in an infinite loop when the - * parent model's global scope utilizes a relation in a query like has or whereHas - */ - public function testDonNotRunParentModelGlobalScopes() - { - /** @var Mockery\MockInterface $parent */ - $eloquentBuilder = m::mock(\Illuminate\Database\Eloquent\Builder::class); - $queryBuilder = m::mock(Builder::class); - $parent = m::mock('EloquentRelationResetModelStub')->makePartial(); - $grammar = m::mock(Grammar::class); - - $eloquentBuilder->shouldReceive('getModel')->andReturn($related = m::mock('StdClass')); - $eloquentBuilder->shouldReceive('getQuery')->andReturn($queryBuilder); - $queryBuilder->shouldReceive('getGrammar')->andReturn($grammar); - $grammar->shouldReceive('wrap'); - $parent->shouldReceive('newQueryWithoutScopes')->andReturn($eloquentBuilder); - - //Test Condition - $parent->shouldReceive('applyGlobalScopes')->andReturn($eloquentBuilder)->never(); - - $relation = new EloquentRelationStub($eloquentBuilder, $parent); - $relation->wrap('test'); - } - -} - -class EloquentRelationResetModelStub extends Illuminate\Database\Eloquent\Model { - //Override method call which would normally go through __call() - public function getQuery() - { - return $this->newQuery()->getQuery(); - } -} - - -class EloquentRelationResetStub extends Illuminate\Database\Eloquent\Builder { - public function __construct() { $this->query = new EloquentRelationQueryStub; } - #[\Override] - public function getModel() { return new EloquentRelationResetModelStub; } -} - - -class EloquentRelationQueryStub extends Illuminate\Database\Query\Builder { - public function __construct() {} -} - -class EloquentRelationStub extends Relation -{ - public function addConstraints() - { - } - - public function addEagerConstraints(array $models) - { - } - - public function initRelation(array $models, $relation) - { - } - - public function match(array $models, Collection $results, $relation) - { - } - - public function getResults() - { - } -} diff --git a/tests/Database/DatabaseMigrationCreatorTest.php b/tests/Database/DatabaseMigrationCreatorTest.php deleted file mode 100755 index be3591431..000000000 --- a/tests/Database/DatabaseMigrationCreatorTest.php +++ /dev/null @@ -1,67 +0,0 @@ -getCreator(); - unset($_SERVER['__migration.creator']); - $creator->afterCreate( - function () { - $_SERVER['__migration.creator'] = true; - } - ); - $creator->expects($this->any())->method('getDatePrefix')->willReturn('foo'); - $creator->getFilesystem()->shouldReceive('get')->once()->with($creator->getStubPath().'/blank.stub')->andReturn('{{class}}'); - $creator->getFilesystem()->shouldReceive('put')->once()->with('foo/foo_create_bar.php', 'CreateBar'); - - $creator->create('create_bar', 'foo'); - - $this->assertTrue($_SERVER['__migration.creator']); - - unset($_SERVER['__migration.creator']); - } - - - public function testTableUpdateMigrationStoresMigrationFile() - { - $creator = $this->getCreator(); - $creator->expects($this->any())->method('getDatePrefix')->willReturn('foo'); - $creator->getFilesystem()->shouldReceive('get')->once()->with($creator->getStubPath().'/update.stub')->andReturn('{{class}} {{table}}'); - $creator->getFilesystem()->shouldReceive('put')->once()->with('foo/foo_create_bar.php', 'CreateBar baz'); - - $creator->create('create_bar', 'foo', 'baz'); - } - - - public function testTableCreationMigrationStoresMigrationFile() - { - $creator = $this->getCreator(); - $creator->expects($this->any())->method('getDatePrefix')->willReturn('foo'); - $creator->getFilesystem()->shouldReceive('get')->once()->with($creator->getStubPath().'/create.stub')->andReturn('{{class}} {{table}}'); - $creator->getFilesystem()->shouldReceive('put')->once()->with('foo/foo_create_bar.php', 'CreateBar baz'); - - $creator->create('create_bar', 'foo', 'baz', true); - } - - - protected function getCreator() - { - $files = m::mock(Filesystem::class); - - return $this->getMock(MigrationCreator::class, ['getDatePrefix'], [$files]); - } - -} diff --git a/tests/Database/DatabaseMigrationInstallCommandTest.php b/tests/Database/DatabaseMigrationInstallCommandTest.php deleted file mode 100755 index fef7eec3e..000000000 --- a/tests/Database/DatabaseMigrationInstallCommandTest.php +++ /dev/null @@ -1,33 +0,0 @@ -shouldReceive('setSource')->once()->with('foo'); - $repo->shouldReceive('createRepository')->once(); - - $this->runCommand($command, ['--database' => 'foo']); - } - - - protected function runCommand($command, $options = []) - { - return $command->run(new Symfony\Component\Console\Input\ArrayInput($options), new Symfony\Component\Console\Output\NullOutput); - } - -} diff --git a/tests/Database/DatabaseMigrationMakeCommandTest.php b/tests/Database/DatabaseMigrationMakeCommandTest.php deleted file mode 100755 index 1065386e6..000000000 --- a/tests/Database/DatabaseMigrationMakeCommandTest.php +++ /dev/null @@ -1,98 +0,0 @@ - __DIR__]; - $command->setLaravel($app); - $creator->allows()->create() - ->once() - ->with('create_foo', __DIR__.'/database/migrations', null, false) - ->andReturn($app['path']); - - $this->runCommand($command, ['name' => 'create_foo']); - } - - - public function testBasicCreateGivesCreatorProperArgumentsWhenTableIsSet() - { - $command = new DatabaseMigrationMakeCommandTestStub($creator = m::mock( - MigrationCreator::class - ), __DIR__.'/vendor'); - $app = ['path' => __DIR__]; - $command->setLaravel($app); - $creator->allows()->create() - ->once() - ->with('create_foo', __DIR__.'/database/migrations', 'users', true) - ->andReturn($app['path']); - - $this->runCommand($command, ['name' => 'create_foo', '--create' => 'users']); - } - - - public function testPackagePathsMayBeUsed() - { - $command = new DatabaseMigrationMakeCommandTestStub($creator = m::mock( - MigrationCreator::class - ), __DIR__.'/vendor'); - $app = ['path' => __DIR__]; - $command->setLaravel($app); - $creator->allows()->create() - ->once() - ->with('create_foo', __DIR__.'/vendor/bar/src/migrations', null, false) - ->andReturn($app['path']); - - $this->runCommand($command, ['name' => 'create_foo', '--package' => 'bar']); - } - - - public function testPackageFallsBackToVendorDirWhenNotExplicit() - { - $command = new DatabaseMigrationMakeCommandTestStub($creator = m::mock( - MigrationCreator::class - ), __DIR__.'/vendor'); - $creator->allows()->create() - ->once() - ->with('create_foo', __DIR__.'/vendor/foo/bar/src/migrations', null, false) - ->andReturn(__DIR__); - - $this->runCommand($command, ['name' => 'create_foo', '--package' => 'foo/bar']); - } - - - protected function runCommand($command, $input = []) - { - return $command->run( - new Symfony\Component\Console\Input\ArrayInput($input), - new Symfony\Component\Console\Output\NullOutput - ); - } - -} - - - -class DatabaseMigrationMakeCommandTestStub extends MigrateMakeCommand -{ - #[\Override] - public function call($command, array $arguments = []) - { - // - } -} diff --git a/tests/Database/DatabaseMigrationMigrateCommandTest.php b/tests/Database/DatabaseMigrationMigrateCommandTest.php deleted file mode 100755 index e454aeda7..000000000 --- a/tests/Database/DatabaseMigrationMigrateCommandTest.php +++ /dev/null @@ -1,123 +0,0 @@ - __DIR__]); - $command->setLaravel($app); - $migrator->shouldReceive('setConnection')->once()->with(null); - $migrator->shouldReceive('run')->once()->with(__DIR__.'/database/migrations', false); - $migrator->shouldReceive('getNotes')->andReturn([]); - $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); - - $this->runCommand($command); - } - - - public function testMigrationRepositoryCreatedWhenNecessary() - { - $params = [$migrator = m::mock(Migrator::class), __DIR__.'/vendor']; - $command = $this->getMock(MigrateCommand::class, ['call'], $params); - $app = new ApplicationDatabaseMigrationStub(['path' => __DIR__]); - $command->setLaravel($app); - $migrator->shouldReceive('setConnection')->once()->with(null); - $migrator->shouldReceive('run')->once()->with(__DIR__.'/database/migrations', false); - $migrator->shouldReceive('getNotes')->andReturn([]); - $migrator->shouldReceive('repositoryExists')->once()->andReturn(false); - $command->expects($this->once())->method('call')->with($this->equalTo('migrate:install'), $this->equalTo( - ['--database' => null] - )); - - $this->runCommand($command); - } - - - public function testPackageIsRespectedWhenMigrating() - { - $command = new MigrateCommand($migrator = m::mock(Migrator::class), __DIR__.'/vendor'); - $command->setLaravel(new ApplicationDatabaseMigrationStub()); - $migrator->shouldReceive('setConnection')->once()->with(null); - $migrator->shouldReceive('run')->once()->with(__DIR__.'/vendor/bar/src/migrations', false); - $migrator->shouldReceive('getNotes')->andReturn([]); - $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); - - $this->runCommand($command, ['--package' => 'bar']); - } - - - public function testVendorPackageIsRespectedWhenMigrating() - { - $command = new MigrateCommand($migrator = m::mock(Migrator::class), __DIR__.'/vendor'); - $command->setLaravel(new ApplicationDatabaseMigrationStub()); - $migrator->shouldReceive('setConnection')->once()->with(null); - $migrator->shouldReceive('run')->once()->with(__DIR__.'/vendor/foo/bar/src/migrations', false); - $migrator->shouldReceive('getNotes')->andReturn([]); - $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); - - $this->runCommand($command, ['--package' => 'foo/bar']); - } - - - public function testTheCommandMayBePretended() - { - $command = new MigrateCommand($migrator = m::mock(Migrator::class), __DIR__.'/vendor'); - $app = new ApplicationDatabaseMigrationStub(['path' => __DIR__]); - $command->setLaravel($app); - $migrator->shouldReceive('setConnection')->once()->with(null); - $migrator->shouldReceive('run')->once()->with(__DIR__.'/database/migrations', true); - $migrator->shouldReceive('getNotes')->andReturn([]); - $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); - - $this->runCommand($command, ['--pretend' => true]); - } - - - public function testTheDatabaseMayBeSet() - { - $command = new MigrateCommand($migrator = m::mock(Migrator::class), __DIR__.'/vendor'); - $app = new ApplicationDatabaseMigrationStub(['path' => __DIR__]); - $command->setLaravel($app); - $migrator->shouldReceive('setConnection')->once()->with('foo'); - $migrator->shouldReceive('run')->once()->with(__DIR__.'/database/migrations', false); - $migrator->shouldReceive('getNotes')->andReturn([]); - $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); - - $this->runCommand($command, ['--database' => 'foo']); - } - - - protected function runCommand($command, $input = []) - { - return $command->run(new Symfony\Component\Console\Input\ArrayInput($input), new Symfony\Component\Console\Output\NullOutput); - } - -} - -class ApplicationDatabaseMigrationStub implements ArrayAccess { - public $content = []; - public $env = 'development'; - public function __construct(array $data = []) { $this->content = $data; } - public function offsetExists($offset): bool - { return isset($this->content[$offset]); } - public function offsetGet($offset): mixed { return $this->content[$offset]; } - public function offsetSet($offset, $value): void { $this->content[$offset] = $value; } - public function offsetUnset($offset): void { unset($this->content[$offset]); } - public function environment() { return $this->env; } -} diff --git a/tests/Database/DatabaseMigrationRepositoryTest.php b/tests/Database/DatabaseMigrationRepositoryTest.php deleted file mode 100755 index 7f289c7e7..000000000 --- a/tests/Database/DatabaseMigrationRepositoryTest.php +++ /dev/null @@ -1,119 +0,0 @@ -getRepository(); - $query = m::mock('stdClass'); - $connectionMock = m::mock(Connection::class); - $repo->getConnectionResolver()->shouldReceive('connection')->with(null)->andReturn($connectionMock); - $repo->getConnection()->shouldReceive('table')->once()->with('migrations')->andReturn($query); - $query->shouldReceive('pluck')->once()->with('migration')->andReturn('bar'); - - $this->assertEquals('bar', $repo->getRan()); - } - - - public function testGetLastMigrationsGetsAllMigrationsWithTheLatestBatchNumber() - { - $repo = $this->getMock(DatabaseMigrationRepository::class, ['getLastBatchNumber'], [ - $resolver = m::mock(ConnectionResolverInterface::class), 'migrations' - ]); - $repo->expects($this->once())->method('getLastBatchNumber')->willReturn(1); - $query = m::mock('stdClass'); - $connectionMock = m::mock(Connection::class); - $repo->getConnectionResolver()->shouldReceive('connection')->with(null)->andReturn($connectionMock); - $repo->getConnection()->shouldReceive('table')->once()->with('migrations')->andReturn($query); - $query->shouldReceive('where')->once()->with('batch', 1)->andReturn($query); - $query->shouldReceive('orderBy')->once()->with('migration', 'desc')->andReturn($query); - $query->shouldReceive('get')->once()->andReturn('foo'); - - $this->assertEquals('foo', $repo->getLast()); - } - - - public function testLogMethodInsertsRecordIntoMigrationTable() - { - $repo = $this->getRepository(); - $query = m::mock('stdClass'); - $connectionMock = m::mock(Connection::class); - $repo->getConnectionResolver()->shouldReceive('connection')->with(null)->andReturn($connectionMock); - $repo->getConnection()->shouldReceive('table')->once()->with('migrations')->andReturn($query); - $query->shouldReceive('insert')->once()->with(['migration' => 'bar', 'batch' => 1]); - - $repo->log('bar', 1); - } - - - public function testDeleteMethodRemovesAMigrationFromTheTable() - { - $repo = $this->getRepository(); - $query = m::mock('stdClass'); - $connectionMock = m::mock(Connection::class); - $repo->getConnectionResolver()->shouldReceive('connection')->with(null)->andReturn($connectionMock); - $repo->getConnection()->shouldReceive('table')->once()->with('migrations')->andReturn($query); - $query->shouldReceive('where')->once()->with('migration', 'foo')->andReturn($query); - $query->shouldReceive('delete')->once(); - $migration = (object) ['migration' => 'foo']; - - $repo->delete($migration); - } - - - public function testGetNextBatchNumberReturnsLastBatchNumberPlusOne() - { - $repo = $this->getMock(DatabaseMigrationRepository::class, ['getLastBatchNumber'], [ - m::mock(ConnectionResolverInterface::class), 'migrations' - ]); - $repo->expects($this->once())->method('getLastBatchNumber')->willReturn(1); - - $this->assertEquals(2, $repo->getNextBatchNumber()); - } - - - public function testGetLastBatchNumberReturnsMaxBatch() - { - $repo = $this->getRepository(); - $query = m::mock('stdClass'); - $connectionMock = m::mock(Connection::class); - $repo->getConnectionResolver()->shouldReceive('connection')->with(null)->andReturn($connectionMock); - $repo->getConnection()->shouldReceive('table')->once()->with('migrations')->andReturn($query); - $query->shouldReceive('max')->once()->andReturn(1); - - $this->assertEquals(1, $repo->getLastBatchNumber()); - } - - - public function testCreateRepositoryCreatesProperDatabaseTable() - { - $repo = $this->getRepository(); - $schema = m::mock('stdClass'); - $connectionMock = m::mock(Connection::class); - $repo->getConnectionResolver()->shouldReceive('connection')->with(null)->andReturn($connectionMock); - $repo->getConnection()->shouldReceive('getSchemaBuilder')->once()->andReturn($schema); - $schema->shouldReceive('create')->once()->with('migrations', m::type('Closure')); - - $repo->createRepository(); - } - - - protected function getRepository() - { - return new DatabaseMigrationRepository(m::mock(ConnectionResolverInterface::class), 'migrations'); - } - -} diff --git a/tests/Database/DatabaseMigrationResetCommandTest.php b/tests/Database/DatabaseMigrationResetCommandTest.php deleted file mode 100755 index 6ac4e6275..000000000 --- a/tests/Database/DatabaseMigrationResetCommandTest.php +++ /dev/null @@ -1,50 +0,0 @@ -setLaravel(new AppDatabaseMigrationStub()); - $migrator->shouldReceive('setConnection')->once()->with(null); - $migrator->shouldReceive('rollback')->twice()->with(false)->andReturn(true, false); - $migrator->shouldReceive('getNotes')->andReturn([]); - - $this->runCommand($command); - } - - - public function testResetCommandCanBePretended() - { - $command = new ResetCommand($migrator = m::mock(Migrator::class)); - $command->setLaravel(new AppDatabaseMigrationStub()); - $migrator->shouldReceive('setConnection')->once()->with('foo'); - $migrator->shouldReceive('rollback')->twice()->with(true)->andReturn(true, false); - $migrator->shouldReceive('getNotes')->andReturn([]); - - $this->runCommand($command, ['--pretend' => true, '--database' => 'foo']); - } - - - protected function runCommand($command, $input = []) - { - return $command->run(new Symfony\Component\Console\Input\ArrayInput($input), new Symfony\Component\Console\Output\NullOutput); - } -} - -class AppDatabaseMigrationStub { - public $env = 'development'; - public function environment() { return $this->env; } -} diff --git a/tests/Database/DatabaseMigrationRollbackCommandTest.php b/tests/Database/DatabaseMigrationRollbackCommandTest.php deleted file mode 100755 index c9fad6a20..000000000 --- a/tests/Database/DatabaseMigrationRollbackCommandTest.php +++ /dev/null @@ -1,51 +0,0 @@ -setLaravel(new AppDatabaseMigrationRollbackStub()); - $migrator->shouldReceive('setConnection')->once()->with(null); - $migrator->shouldReceive('rollback')->once()->with(false); - $migrator->shouldReceive('getNotes')->andReturn([]); - - $this->runCommand($command); - } - - - public function testRollbackCommandCanBePretended() - { - $command = new RollbackCommand($migrator = m::mock(Migrator::class)); - $command->setLaravel(new AppDatabaseMigrationRollbackStub()); - $migrator->shouldReceive('setConnection')->once()->with('foo'); - $migrator->shouldReceive('rollback')->once()->with(true); - $migrator->shouldReceive('getNotes')->andReturn([]); - - $this->runCommand($command, ['--pretend' => true, '--database' => 'foo']); - } - - - protected function runCommand($command, $input = []) - { - return $command->run(new Symfony\Component\Console\Input\ArrayInput($input), new Symfony\Component\Console\Output\NullOutput); - } - -} - -class AppDatabaseMigrationRollbackStub { - public $env = 'development'; - public function environment() { return $this->env; } -} diff --git a/tests/Database/DatabaseMigratorTest.php b/tests/Database/DatabaseMigratorTest.php deleted file mode 100755 index 5b236a5bc..000000000 --- a/tests/Database/DatabaseMigratorTest.php +++ /dev/null @@ -1,223 +0,0 @@ -getMock( - Migrator::class, - ['resolve'], - [ - m::mock(MigrationRepositoryInterface::class), - $resolver = m::mock(ConnectionResolverInterface::class), - m::mock(Filesystem::class), - ] - ); - $migrator->getFilesystem()->shouldReceive('glob')->once()->with(__DIR__.'/*_*.php')->andReturn([ - __DIR__.'/2_bar.php', - __DIR__.'/1_foo.php', - __DIR__.'/3_baz.php', - ]); - - $migrator->getFilesystem()->shouldReceive('requireOnce')->with(__DIR__.'/2_bar.php'); - $migrator->getFilesystem()->shouldReceive('requireOnce')->with(__DIR__.'/1_foo.php'); - $migrator->getFilesystem()->shouldReceive('requireOnce')->with(__DIR__.'/3_baz.php'); - - $migrator->getRepository()->shouldReceive('getRan')->once()->andReturn([ - '1_foo', - ]); - $migrator->getRepository()->shouldReceive('getNextBatchNumber')->once()->andReturn(1); - $migrator->getRepository()->shouldReceive('log')->once()->with('2_bar', 1); - $migrator->getRepository()->shouldReceive('log')->once()->with('3_baz', 1); - $barMock = m::mock(stdClass::class); - $barMock->shouldReceive('up')->once(); - $bazMock = m::mock(stdClass::class); - $bazMock->shouldReceive('up')->once(); - - $migrator - ->expects($this->exactly(2)) - ->method('resolve') - ->withConsecutive([$this->equalTo('2_bar')], [$this->equalTo('3_baz')]) - ->willReturnOnConsecutiveCalls($barMock, $bazMock); - - $migrator->run(__DIR__); - } - - - public function testUpMigrationCanBePretended() - { - $migrator = $this->getMock(Migrator::class, ['resolve'], [ - m::mock(MigrationRepositoryInterface::class), - $resolver = m::mock(ConnectionResolverInterface::class), - m::mock(Filesystem::class), - ]); - $migrator->getFilesystem()->shouldReceive('glob')->once()->with(__DIR__.'/*_*.php')->andReturn([ - __DIR__.'/2_bar.php', - __DIR__.'/1_foo.php', - __DIR__.'/3_baz.php', - ]); - $migrator->getFilesystem()->shouldReceive('requireOnce')->with(__DIR__.'/2_bar.php'); - $migrator->getFilesystem()->shouldReceive('requireOnce')->with(__DIR__.'/1_foo.php'); - $migrator->getFilesystem()->shouldReceive('requireOnce')->with(__DIR__.'/3_baz.php'); - $migrator->getRepository()->shouldReceive('getRan')->once()->andReturn([ - '1_foo', - ]); - $migrator->getRepository()->shouldReceive('getNextBatchNumber')->once()->andReturn(1); - - $barMock = m::mock(stdClass::class); - $barMock->shouldReceive('getConnection')->once()->andReturn(null); - $barMock->shouldReceive('up')->once(); - - $bazMock = m::mock(stdClass::class); - $bazMock->shouldReceive('getConnection')->once()->andReturn(null); - $bazMock->shouldReceive('up')->once(); - - $migrator - ->expects($this->exactly(2)) - ->method('resolve') - ->withConsecutive([$this->equalTo('2_bar')], [$this->equalTo('3_baz')]) - ->willReturnOnConsecutiveCalls($barMock, $bazMock); - - $connection = m::mock(stdClass::class); - $connection->shouldReceive('pretend')->with(m::type('Closure'))->andReturnUsing(function($closure) - { - $closure(); - return [['query' => 'foo']]; - }, - function($closure) - { - $closure(); - return [['query' => 'bar']]; - }); - $resolver->shouldReceive('connection')->with(null)->andReturn($connection); - - $migrator->run(__DIR__, true); - } - - - public function testNothingIsDoneWhenNoMigrationsAreOutstanding() - { - $migrator = $this->getMock(Migrator::class, ['resolve'], [ - m::mock(MigrationRepositoryInterface::class), - $resolver = m::mock(ConnectionResolverInterface::class), - m::mock(Filesystem::class), - ]); - $migrator->getFilesystem()->shouldReceive('glob')->once()->with(__DIR__.'/*_*.php')->andReturn([ - __DIR__.'/1_foo.php', - ]); - $migrator->getFilesystem()->shouldReceive('requireOnce')->with(__DIR__.'/1_foo.php'); - $migrator->getRepository()->shouldReceive('getRan')->once()->andReturn([ - '1_foo', - ]); - - $migrator->run(__DIR__); - } - - - public function testLastBatchOfMigrationsCanBeRolledBack() - { - $migrator = $this->getMock(Migrator::class, ['resolve'], [ - m::mock(MigrationRepositoryInterface::class), - $resolver = m::mock(ConnectionResolverInterface::class), - m::mock(Filesystem::class), - ]); - $migrator->getRepository()->shouldReceive('getLast')->once()->andReturn([ - $fooMigration = new MigratorTestMigrationStub('foo'), - $barMigration = new MigratorTestMigrationStub('bar'), - ]); - - $barMock = m::mock(stdClass::class); - $barMock->shouldReceive('down')->once(); - - $fooMock = m::mock(stdClass::class); - $fooMock->shouldReceive('down')->once(); - - $migrator - ->expects($this->exactly(2)) - ->method('resolve') - ->withConsecutive([$this->equalTo('foo')], [$this->equalTo('bar')]) - ->willReturnOnConsecutiveCalls($barMock, $fooMock); - - $migrator->getRepository()->shouldReceive('delete')->once()->with($barMigration); - $migrator->getRepository()->shouldReceive('delete')->once()->with($fooMigration); - - $migrator->rollback(); - } - - - public function testRollbackMigrationsCanBePretended() - { - $migrator = $this->getMock(Migrator::class, ['resolve'], [ - m::mock(MigrationRepositoryInterface::class), - $resolver = m::mock(ConnectionResolverInterface::class), - m::mock(Filesystem::class), - ]); - $migrator->getRepository()->shouldReceive('getLast')->once()->andReturn([ - $fooMigration = new MigratorTestMigrationStub('foo'), - $barMigration = new MigratorTestMigrationStub('bar'), - ]); - - $barMock = m::mock(stdClass::class); - $barMock->shouldReceive('getConnection')->once()->andReturn(null); - $barMock->shouldReceive('down')->once(); - - $fooMock = m::mock(stdClass::class); - $fooMock->shouldReceive('getConnection')->once()->andReturn(null); - $fooMock->shouldReceive('down')->once(); - - $migrator - ->expects($this->exactly(2)) - ->method('resolve') - ->withConsecutive([$this->equalTo('foo')], [$this->equalTo('bar')]) - ->willReturnOnConsecutiveCalls($barMock, $fooMock); - - $connection = m::mock(stdClass::class); - $connection->shouldReceive('pretend')->with(m::type('Closure'))->andReturnUsing(function($closure) - { - $closure(); - return [['query' => 'bar']]; - }, - function($closure) - { - $closure(); - return [['query' => 'foo']]; - }); - $resolver->shouldReceive('connection')->with(null)->andReturn($connection); - - $migrator->rollback(true); - } - - - public function testNothingIsRolledBackWhenNothingInRepository() - { - $migrator = $this->getMock(Migrator::class, ['resolve'], [ - m::mock(MigrationRepositoryInterface::class), - $resolver = m::mock(ConnectionResolverInterface::class), - m::mock(Filesystem::class), - ]); - $migrator->getRepository()->shouldReceive('getLast')->once()->andReturn([]); - - $migrator->rollback(); - } - -} - - -class MigratorTestMigrationStub { - public function __construct($migration) { $this->migration = $migration; } - public $migration; -} diff --git a/tests/Database/DatabaseMySqlProcessorTest.php b/tests/Database/DatabaseMySqlProcessorTest.php deleted file mode 100644 index 2ef41c893..000000000 --- a/tests/Database/DatabaseMySqlProcessorTest.php +++ /dev/null @@ -1,22 +0,0 @@ - 'id'], ['column_name' => 'name'], ['column_name' => 'email']]; - $expected = ['id', 'name', 'email']; - $this->assertEquals($expected, $processor->processColumnListing($listing)); - - // convert listing to objects to simulate PDO::FETCH_CLASS - foreach($listing as &$row) { - $row = (object) $row; - } - - $this->assertEquals($expected, $processor->processColumnListing($listing)); - } - -} diff --git a/tests/Database/DatabaseMySqlSchemaGrammarTest.php b/tests/Database/DatabaseMySqlSchemaGrammarTest.php deleted file mode 100755 index fb852688b..000000000 --- a/tests/Database/DatabaseMySqlSchemaGrammarTest.php +++ /dev/null @@ -1,544 +0,0 @@ -create(); - $blueprint->increments('id'); - $blueprint->string('email'); - - $conn = $this->getConnection(); - $conn->shouldReceive('getConfig')->once()->with('charset')->andReturn('utf8'); - $conn->shouldReceive('getConfig')->once()->with('collation')->andReturn('utf8_unicode_ci'); - - $statements = $blueprint->toSql($conn, $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('create table `users` (`id` int unsigned not null auto_increment primary key, `email` varchar(255) not null) default character set utf8 collate utf8_unicode_ci', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->increments('id'); - $blueprint->string('email'); - - $conn = $this->getConnection(); - $conn->shouldReceive('getConfig')->andReturn(null); - - $statements = $blueprint->toSql($conn, $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `id` int unsigned not null auto_increment primary key, add `email` varchar(255) not null', $statements[0]); - } - - - public function testBasicCreateTableWithPrefix() - { - $blueprint = new Blueprint('users'); - $blueprint->create(); - $blueprint->increments('id'); - $blueprint->string('email'); - $grammar = $this->getGrammar(); - $grammar->setTablePrefix('prefix_'); - - $conn = $this->getConnection(); - $conn->shouldReceive('getConfig')->andReturn(null); - - $statements = $blueprint->toSql($conn, $grammar); - - $this->assertCount(1, $statements); - $this->assertEquals('create table `prefix_users` (`id` int unsigned not null auto_increment primary key, `email` varchar(255) not null)', $statements[0]); - } - - - public function testDropTable() - { - $blueprint = new Blueprint('users'); - $blueprint->drop(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('drop table `users`', $statements[0]); - } - - - public function testDropTableIfExists() - { - $blueprint = new Blueprint('users'); - $blueprint->dropIfExists(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('drop table if exists `users`', $statements[0]); - } - - - public function testDropColumn() - { - $blueprint = new Blueprint('users'); - $blueprint->dropColumn('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` drop `foo`', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->dropColumn(['foo', 'bar']); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` drop `foo`, drop `bar`', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->dropColumn('foo', 'bar'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` drop `foo`, drop `bar`', $statements[0]); - } - - - public function testDropPrimary() - { - $blueprint = new Blueprint('users'); - $blueprint->dropPrimary(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` drop primary key', $statements[0]); - } - - - public function testDropUnique() - { - $blueprint = new Blueprint('users'); - $blueprint->dropUnique('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` drop index foo', $statements[0]); - } - - - public function testDropIndex() - { - $blueprint = new Blueprint('users'); - $blueprint->dropIndex('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` drop index foo', $statements[0]); - } - - - public function testDropForeign() - { - $blueprint = new Blueprint('users'); - $blueprint->dropForeign('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` drop foreign key foo', $statements[0]); - } - - - public function testDropTimestamps() - { - $blueprint = new Blueprint('users'); - $blueprint->dropTimestamps(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` drop `created_at`, drop `updated_at`', $statements[0]); - } - - - public function testRenameTable() - { - $blueprint = new Blueprint('users'); - $blueprint->rename('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('rename table `users` to `foo`', $statements[0]); - } - - - public function testAddingPrimaryKey() - { - $blueprint = new Blueprint('users'); - $blueprint->primary('foo', 'bar'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add primary key bar(`foo`)', $statements[0]); - } - - - public function testAddingUniqueKey() - { - $blueprint = new Blueprint('users'); - $blueprint->unique('foo', 'bar'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add unique bar(`foo`)', $statements[0]); - } - - - public function testAddingIndex() - { - $blueprint = new Blueprint('users'); - $blueprint->index(['foo', 'bar'], 'baz'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add index baz(`foo`, `bar`)', $statements[0]); - } - - - public function testAddingForeignKey() - { - $blueprint = new Blueprint('users'); - $blueprint->foreign('foo_id')->references('id')->on('orders'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add constraint users_foo_id_foreign foreign key (`foo_id`) references `orders` (`id`)', $statements[0]); - } - - - public function testAddingIncrementingID() - { - $blueprint = new Blueprint('users'); - $blueprint->increments('id'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `id` int unsigned not null auto_increment primary key', $statements[0]); - } - - - public function testAddingBigIncrementingID() - { - $blueprint = new Blueprint('users'); - $blueprint->bigIncrements('id'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `id` bigint unsigned not null auto_increment primary key', $statements[0]); - } - - - public function testAddingColumnAfterAnotherColumn() - { - $blueprint = new Blueprint('users'); - $blueprint->string('name')->after('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `name` varchar(255) not null after `foo`', $statements[0]); - } - - - public function testAddingString() - { - $blueprint = new Blueprint('users'); - $blueprint->string('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` varchar(255) not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->string('foo', 100); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` varchar(100) not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->string('foo', 100)->nullable()->default('bar'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` varchar(100) null default \'bar\'', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->string('foo', 100)->nullable()->default(new Illuminate\Database\Query\Expression('CURRENT TIMESTAMP')); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` varchar(100) null default CURRENT TIMESTAMP', $statements[0]); - } - - - public function testAddingText() - { - $blueprint = new Blueprint('users'); - $blueprint->text('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` text not null', $statements[0]); - } - - - public function testAddingBigInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->bigInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` bigint not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->bigInteger('foo', true); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` bigint not null auto_increment primary key', $statements[0]); - } - - - public function testAddingInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->integer('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` int not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->integer('foo', true); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` int not null auto_increment primary key', $statements[0]); - } - - - public function testAddingMediumInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->mediumInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` mediumint not null', $statements[0]); - } - - - public function testAddingSmallInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->smallInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` smallint not null', $statements[0]); - } - - - public function testAddingTinyInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->tinyInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` tinyint not null', $statements[0]); - } - - - public function testAddingFloat() - { - $blueprint = new Blueprint('users'); - $blueprint->float('foo', 5, 2); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` float(5, 2) not null', $statements[0]); - } - - - public function testAddingDouble() - { - $blueprint = new Blueprint('users'); - $blueprint->double('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` double not null', $statements[0]); - } - - - public function testAddingDoubleSpecifyingPrecision() - { - $blueprint = new Blueprint('users'); - $blueprint->double('foo', 15, 8); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` double(15, 8) not null', $statements[0]); - } - - - public function testAddingDecimal() - { - $blueprint = new Blueprint('users'); - $blueprint->decimal('foo', 5, 2); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` decimal(5, 2) not null', $statements[0]); - } - - - public function testAddingBoolean() - { - $blueprint = new Blueprint('users'); - $blueprint->boolean('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` tinyint(1) not null', $statements[0]); - } - - - public function testAddingEnum() - { - $blueprint = new Blueprint('users'); - $blueprint->enum('foo', ['bar', 'baz']); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` enum(\'bar\', \'baz\') not null', $statements[0]); - } - - - public function testAddingDate() - { - $blueprint = new Blueprint('users'); - $blueprint->date('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` date not null', $statements[0]); - } - - - public function testAddingDateTime() - { - $blueprint = new Blueprint('users'); - $blueprint->dateTime('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` datetime not null', $statements[0]); - } - - - public function testAddingTime() - { - $blueprint = new Blueprint('users'); - $blueprint->time('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` time not null', $statements[0]); - } - - - public function testAddingTimeStamp() - { - $blueprint = new Blueprint('users'); - $blueprint->timestamp('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` timestamp default 0 not null', $statements[0]); - } - - - public function testAddingTimeStamps() - { - $blueprint = new Blueprint('users'); - $blueprint->timestamps(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `created_at` datetime not null, add `updated_at` datetime not null', $statements[0]); - } - - - public function testAddingTimeStampsWithRealTimestampColumnType() - { - $blueprint = new Blueprint('users'); - $blueprint->timestampsWithTimestampColumnType(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `created_at` timestamp default 0 not null, add `updated_at` timestamp default 0 not null', $statements[0]); - } - - - public function testAddingNullableTimeStamps() - { - $blueprint = new Blueprint('users'); - $blueprint->nullableTimestamps(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `created_at` datetime null, add `updated_at` datetime null', $statements[0]); - } - - - public function testAddingRememberToken() - { - $blueprint = new Blueprint('users'); - $blueprint->rememberToken(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `remember_token` varchar(100) null', $statements[0]); - } - - - public function testAddingBinary() - { - $blueprint = new Blueprint('users'); - $blueprint->binary('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table `users` add `foo` blob not null', $statements[0]); - } - - - protected function getConnection() - { - return m::mock(Connection::class); - } - - - public function getGrammar() - { - return new Illuminate\Database\Schema\Grammars\MySqlGrammar; - } - -} diff --git a/tests/Database/DatabasePostgresProcessorTest.php b/tests/Database/DatabasePostgresProcessorTest.php deleted file mode 100644 index abef1d890..000000000 --- a/tests/Database/DatabasePostgresProcessorTest.php +++ /dev/null @@ -1,25 +0,0 @@ - 'id'], ['column_name' => 'name'], ['column_name' => 'email']]; - $expected = ['id', 'name', 'email']; - - $this->assertEquals($expected, $processor->processColumnListing($listing)); - - // convert listing to objects to simulate PDO::FETCH_CLASS - foreach($listing as &$row) - { - $row = (object) $row; - } - - $this->assertEquals($expected, $processor->processColumnListing($listing)); - } - -} diff --git a/tests/Database/DatabasePostgresSchemaGrammarTest.php b/tests/Database/DatabasePostgresSchemaGrammarTest.php deleted file mode 100755 index d616ec689..000000000 --- a/tests/Database/DatabasePostgresSchemaGrammarTest.php +++ /dev/null @@ -1,443 +0,0 @@ -create(); - $blueprint->increments('id'); - $blueprint->string('email'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('create table "users" ("id" serial primary key not null, "email" varchar(255) not null)', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->increments('id'); - $blueprint->string('email'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "id" serial primary key not null, add column "email" varchar(255) not null', $statements[0]); - } - - - public function testDropTable() - { - $blueprint = new Blueprint('users'); - $blueprint->drop(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('drop table "users"', $statements[0]); - } - - - public function testDropTableIfExists() - { - $blueprint = new Blueprint('users'); - $blueprint->dropIfExists(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('drop table if exists "users"', $statements[0]); - } - - - public function testDropColumn() - { - $blueprint = new Blueprint('users'); - $blueprint->dropColumn('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" drop column "foo"', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->dropColumn(['foo', 'bar']); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" drop column "foo", drop column "bar"', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->dropColumn('foo', 'bar'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" drop column "foo", drop column "bar"', $statements[0]); - } - - - public function testDropPrimary() - { - $blueprint = new Blueprint('users'); - $blueprint->dropPrimary(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" drop constraint users_pkey', $statements[0]); - } - - - public function testDropUnique() - { - $blueprint = new Blueprint('users'); - $blueprint->dropUnique('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" drop constraint foo', $statements[0]); - } - - - public function testDropIndex() - { - $blueprint = new Blueprint('users'); - $blueprint->dropIndex('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('drop index foo', $statements[0]); - } - - - public function testDropForeign() - { - $blueprint = new Blueprint('users'); - $blueprint->dropForeign('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" drop constraint foo', $statements[0]); - } - - - public function testDropTimestamps() - { - $blueprint = new Blueprint('users'); - $blueprint->dropTimestamps(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" drop column "created_at", drop column "updated_at"', $statements[0]); - } - - - public function testRenameTable() - { - $blueprint = new Blueprint('users'); - $blueprint->rename('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" rename to "foo"', $statements[0]); - } - - - public function testAddingPrimaryKey() - { - $blueprint = new Blueprint('users'); - $blueprint->primary('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add primary key ("foo")', $statements[0]); - } - - - public function testAddingUniqueKey() - { - $blueprint = new Blueprint('users'); - $blueprint->unique('foo', 'bar'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add constraint bar unique ("foo")', $statements[0]); - } - - - public function testAddingIndex() - { - $blueprint = new Blueprint('users'); - $blueprint->index(['foo', 'bar'], 'baz'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('create index baz on "users" ("foo", "bar")', $statements[0]); - } - - - public function testAddingIncrementingID() - { - $blueprint = new Blueprint('users'); - $blueprint->increments('id'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "id" serial primary key not null', $statements[0]); - } - - - public function testAddingBigIncrementingID() - { - $blueprint = new Blueprint('users'); - $blueprint->bigIncrements('id'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "id" bigserial primary key not null', $statements[0]); - } - - - public function testAddingString() - { - $blueprint = new Blueprint('users'); - $blueprint->string('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" varchar(255) not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->string('foo', 100); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" varchar(100) not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->string('foo', 100)->nullable()->default('bar'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" varchar(100) null default \'bar\'', $statements[0]); - } - - - public function testAddingText() - { - $blueprint = new Blueprint('users'); - $blueprint->text('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" text not null', $statements[0]); - } - - - public function testAddingBigInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->bigInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" bigint not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->bigInteger('foo', true); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" bigserial primary key not null', $statements[0]); - } - - - public function testAddingInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->integer('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" integer not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->integer('foo', true); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" serial primary key not null', $statements[0]); - } - - - public function testAddingMediumInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->mediumInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" integer not null', $statements[0]); - } - - - public function testAddingTinyInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->tinyInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" smallint not null', $statements[0]); - } - - - public function testAddingSmallInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->smallInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" smallint not null', $statements[0]); - } - - - public function testAddingFloat() - { - $blueprint = new Blueprint('users'); - $blueprint->float('foo', 5, 2); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" real not null', $statements[0]); - } - - - public function testAddingDouble() - { - $blueprint = new Blueprint('users'); - $blueprint->double('foo', 15, 8); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" double precision not null', $statements[0]); - } - - - public function testAddingDecimal() - { - $blueprint = new Blueprint('users'); - $blueprint->decimal('foo', 5, 2); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" decimal(5, 2) not null', $statements[0]); - } - - - public function testAddingBoolean() - { - $blueprint = new Blueprint('users'); - $blueprint->boolean('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" boolean not null', $statements[0]); - } - - - public function testAddingEnum() - { - $blueprint = new Blueprint('users'); - $blueprint->enum('foo', ['bar', 'baz']); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" varchar(255) check ("foo" in (\'bar\', \'baz\')) not null', $statements[0]); - } - - - public function testAddingDate() - { - $blueprint = new Blueprint('users'); - $blueprint->date('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" date not null', $statements[0]); - } - - - public function testAddingDateTime() - { - $blueprint = new Blueprint('users'); - $blueprint->dateTime('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" timestamp not null', $statements[0]); - } - - - public function testAddingTime() - { - $blueprint = new Blueprint('users'); - $blueprint->time('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" time not null', $statements[0]); - } - - - public function testAddingTimeStamp() - { - $blueprint = new Blueprint('users'); - $blueprint->timestamp('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" timestamp not null', $statements[0]); - } - - - public function testAddingTimeStamps() - { - $blueprint = new Blueprint('users'); - $blueprint->timestamps(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "created_at" timestamp not null, add column "updated_at" timestamp not null', $statements[0]); - } - - - public function testAddingBinary() - { - $blueprint = new Blueprint('users'); - $blueprint->binary('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" bytea not null', $statements[0]); - } - - - protected function getConnection() - { - return m::mock(Connection::class); - } - - - public function getGrammar() - { - return new Illuminate\Database\Schema\Grammars\PostgresGrammar; - } - -} diff --git a/tests/Database/DatabaseProcessorTest.php b/tests/Database/DatabaseProcessorTest.php deleted file mode 100755 index 9575845ff..000000000 --- a/tests/Database/DatabaseProcessorTest.php +++ /dev/null @@ -1,43 +0,0 @@ -createMock(ProcessorTestPDOStub::class); - $pdo->expects($this->once())->method('lastInsertId')->with($this->equalTo('id'))->willReturn('1'); - $connection = m::mock(Connection::class); - $connection->shouldReceive('insert')->once()->with('sql', ['foo']); - $connection->shouldReceive('getPdo')->once()->andReturn($pdo); - $builder = m::mock(Builder::class); - $builder->shouldReceive('getConnection')->andReturn($connection); - $processor = new Illuminate\Database\Query\Processors\Processor; - $result = $processor->processInsertGetId($builder, 'sql', ['foo'], 'id'); - $this->assertSame(1, $result); - } - -} - -class ProcessorTestPDOStub extends PDO { - - public function __construct() { - // - } - - public function lastInsertId($sequence = null): string|false { - // - } - -} diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php deleted file mode 100755 index ffc73c47c..000000000 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ /dev/null @@ -1,1530 +0,0 @@ -getBuilder(); - $builder->select('*')->from('users'); - $this->assertEquals('select * from "users"', $builder->toSql()); - } - - - public function testBasicSelectUseWritePdo(): void - { - $builder = $this->getMySqlBuilderWithProcessor(); - $builder->getConnection()->shouldReceive('select')->once() - ->with('select * from `users`', [], false); - $builder->useWritePdo()->select('*')->from('users')->get(); - - $builder = $this->getMySqlBuilderWithProcessor(); - $builder->getConnection()->shouldReceive('select')->once() - ->with('select * from `users`', []); - $builder->select('*')->from('users')->get(); - } - - - public function testBasicTableWrappingProtectsQuotationMarks(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('some"table'); - $this->assertEquals('select * from "some""table"', $builder->toSql()); - } - - public function testAliasWrappingAsWholeConstant(): void - { - $builder = $this->getBuilder(); - $builder->select('x.y as foo.bar')->from('baz'); - $this->assertEquals('select "x"."y" as "foo.bar" from "baz"', $builder->toSql()); - } - - public function testAddingSelects(): void - { - $builder = $this->getBuilder(); - $builder->select('foo')->addSelect('bar')->addSelect(['baz', 'boom'])->from('users'); - $this->assertEquals('select "foo", "bar", "baz", "boom" from "users"', $builder->toSql()); - } - - - public function testBasicSelectWithPrefix(): void - { - $builder = $this->getBuilder(); - $builder->getGrammar()->setTablePrefix('prefix_'); - $builder->select('*')->from('users'); - $this->assertEquals('select * from "prefix_users"', $builder->toSql()); - } - - - public function testBasicSelectDistinct(): void - { - $builder = $this->getBuilder(); - $builder->distinct()->select('foo', 'bar')->from('users'); - $this->assertEquals('select distinct "foo", "bar" from "users"', $builder->toSql()); - } - - - public function testSelectWithCaching(): void - { - $cache = m::mock('stdClass'); - $driver = m::mock('stdClass'); - $query = $this->setupCacheTestQuery($cache, $driver); - - $query = $query->remember(5); - - $driver->shouldReceive('remember') - ->once() - ->with($query->getCacheKey(), m::type(\DateTimeInterface::class), m::type('Closure')) - ->andReturnUsing(function($key, $minutes, $callback) { return $callback(); }); - - - $this->assertEquals($query->get(), ['results']); - } - - - public function testSelectWithCachingForever(): void - { - $cache = m::mock('stdClass'); - $driver = m::mock('stdClass'); - $query = $this->setupCacheTestQuery($cache, $driver); - - $query = $query->rememberForever(); - - $driver->shouldReceive('rememberForever') - ->once() - ->with($query->getCacheKey(), m::type('Closure')) - ->andReturnUsing(function($key, $callback) { return $callback(); }); - - - - $this->assertEquals($query->get(), ['results']); - } - - - public function testSelectWithCachingAndTags(): void - { - $taggedCache = m::mock('StdClass'); - $cache = m::mock('stdClass'); - $driver = m::mock('stdClass'); - - $driver->shouldReceive('tags') - ->once() - ->with(['foo','bar']) - ->andReturn($taggedCache); - - $query = $this->setupCacheTestQuery($cache, $driver); - $query = $query->cacheTags(['foo', 'bar'])->remember(5); - - $taggedCache->shouldReceive('remember') - ->once() - ->with($query->getCacheKey(), m::type(\DateTimeInterface::class), m::type('Closure')) - ->andReturnUsing(function($key, $minutes, $callback) { return $callback(); }); - - $this->assertEquals($query->get(), ['results']); - } - - - public function testBasicAlias(): void - { - $builder = $this->getBuilder(); - $builder->select('foo as bar')->from('users'); - $this->assertEquals('select "foo" as "bar" from "users"', $builder->toSql()); - } - - - public function testBasicTableWrapping(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('public.users'); - $this->assertEquals('select * from "public"."users"', $builder->toSql()); - } - - - public function testBasicWheres(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1); - $this->assertEquals('select * from "users" where "id" = ?', $builder->toSql()); - $this->assertEquals([0 => 1], $builder->getBindings()); - } - - - public function testMySqlWrappingProtectsQuotationMarks(): void - { - $builder = $this->getMySqlBuilder(); - $builder->select('*')->From('some`table'); - $this->assertEquals('select * from `some``table`', $builder->toSql()); - } - - - public function testWhereDayMySql(): void - { - $builder = $this->getMySqlBuilder(); - $builder->select('*')->from('users')->whereDay('created_at', '=', 1); - $this->assertEquals('select * from `users` where day(`created_at`) = ?', $builder->toSql()); - $this->assertEquals([0 => 1], $builder->getBindings()); - } - - - public function testWhereMonthMySql(): void - { - $builder = $this->getMySqlBuilder(); - $builder->select('*')->from('users')->whereMonth('created_at', '=', 5); - $this->assertEquals('select * from `users` where month(`created_at`) = ?', $builder->toSql()); - $this->assertEquals([0 => 5], $builder->getBindings()); - } - - - public function testWhereYearMySql(): void - { - $builder = $this->getMySqlBuilder(); - $builder->select('*')->from('users')->whereYear('created_at', '=', 2014); - $this->assertEquals('select * from `users` where year(`created_at`) = ?', $builder->toSql()); - $this->assertEquals([0 => 2014], $builder->getBindings()); - } - - - public function testWhereDayPostgres(): void - { - $builder = $this->getPostgresBuilder(); - $builder->select('*')->from('users')->whereDay('created_at', '=', 1); - $this->assertEquals('select * from "users" where day("created_at") = ?', $builder->toSql()); - $this->assertEquals([0 => 1], $builder->getBindings()); - } - - - public function testWhereMonthPostgres(): void - { - $builder = $this->getPostgresBuilder(); - $builder->select('*')->from('users')->whereMonth('created_at', '=', 5); - $this->assertEquals('select * from "users" where month("created_at") = ?', $builder->toSql()); - $this->assertEquals([0 => 5], $builder->getBindings()); - } - - - public function testWhereYearPostgres(): void - { - $builder = $this->getPostgresBuilder(); - $builder->select('*')->from('users')->whereYear('created_at', '=', 2014); - $this->assertEquals('select * from "users" where year("created_at") = ?', $builder->toSql()); - $this->assertEquals([0 => 2014], $builder->getBindings()); - } - - - public function testWhereDaySqlite(): void - { - $builder = $this->getSQLiteBuilder(); - $builder->select('*')->from('users')->whereDay('created_at', '=', 1); - $this->assertEquals('select * from "users" where strftime(\'%d\', "created_at") = ?', $builder->toSql()); - $this->assertEquals([0 => 1], $builder->getBindings()); - } - - - public function testWhereMonthSqlite(): void - { - $builder = $this->getSQLiteBuilder(); - $builder->select('*')->from('users')->whereMonth('created_at', '=', 5); - $this->assertEquals('select * from "users" where strftime(\'%m\', "created_at") = ?', $builder->toSql()); - $this->assertEquals([0 => 5], $builder->getBindings()); - } - - - public function testWhereYearSqlite(): void - { - $builder = $this->getSQLiteBuilder(); - $builder->select('*')->from('users')->whereYear('created_at', '=', 2014); - $this->assertEquals('select * from "users" where strftime(\'%Y\', "created_at") = ?', $builder->toSql()); - $this->assertEquals([0 => 2014], $builder->getBindings()); - } - - - public function testWhereDaySqlServer(): void - { - $builder = $this->getPostgresBuilder(); - $builder->select('*')->from('users')->whereDay('created_at', '=', 1); - $this->assertEquals('select * from "users" where day("created_at") = ?', $builder->toSql()); - $this->assertEquals([0 => 1], $builder->getBindings()); - } - - - public function testWhereMonthSqlServer(): void - { - $builder = $this->getPostgresBuilder(); - $builder->select('*')->from('users')->whereMonth('created_at', '=', 5); - $this->assertEquals('select * from "users" where month("created_at") = ?', $builder->toSql()); - $this->assertEquals([0 => 5], $builder->getBindings()); - } - - - public function testWhereYearSqlServer(): void - { - $builder = $this->getPostgresBuilder(); - $builder->select('*')->from('users')->whereYear('created_at', '=', 2014); - $this->assertEquals('select * from "users" where year("created_at") = ?', $builder->toSql()); - $this->assertEquals([0 => 2014], $builder->getBindings()); - } - - - public function testWhereBetweens(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->whereBetween('id', [1, 2]); - $this->assertEquals('select * from "users" where "id" between ? and ?', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 2], $builder->getBindings()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->whereNotBetween('id', [1, 2]); - $this->assertEquals('select * from "users" where "id" not between ? and ?', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 2], $builder->getBindings()); - } - - - public function testBasicOrWheres(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1)->orWhere('email', '=', 'foo'); - $this->assertEquals('select * from "users" where "id" = ? or "email" = ?', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 'foo'], $builder->getBindings()); - } - - - public function testRawWheres(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->whereRaw('id = ? or email = ?', [1, 'foo']); - $this->assertEquals('select * from "users" where id = ? or email = ?', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 'foo'], $builder->getBindings()); - } - - - public function testRawOrWheres(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1)->orWhereRaw('email = ?', ['foo']); - $this->assertEquals('select * from "users" where "id" = ? or email = ?', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 'foo'], $builder->getBindings()); - } - - - public function testBasicWhereIns(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->whereIn('id', [1, 2, 3]); - $this->assertEquals('select * from "users" where "id" in (?, ?, ?)', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 2, 2 => 3], $builder->getBindings()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1)->orWhereIn('id', [1, 2, 3]); - $this->assertEquals('select * from "users" where "id" = ? or "id" in (?, ?, ?)', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 1, 2 => 2, 3 => 3], $builder->getBindings()); - } - - - public function testBasicWhereNotIns(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->whereNotIn('id', [1, 2, 3]); - $this->assertEquals('select * from "users" where "id" not in (?, ?, ?)', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 2, 2 => 3], $builder->getBindings()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1)->orWhereNotIn('id', [1, 2, 3]); - $this->assertEquals('select * from "users" where "id" = ? or "id" not in (?, ?, ?)', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 1, 2 => 2, 3 => 3], $builder->getBindings()); - } - - - public function testEmptyWhereIns(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->whereIn('id', []); - $this->assertEquals('select * from "users" where 0 = 1', $builder->toSql()); - $this->assertEquals([], $builder->getBindings()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1)->orWhereIn('id', []); - $this->assertEquals('select * from "users" where "id" = ? or 0 = 1', $builder->toSql()); - $this->assertEquals([0 => 1], $builder->getBindings()); - } - - - public function testEmptyWhereNotIns(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->whereNotIn('id', []); - $this->assertEquals('select * from "users" where 1 = 1', $builder->toSql()); - $this->assertEquals([], $builder->getBindings()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1)->orWhereNotIn('id', []); - $this->assertEquals('select * from "users" where "id" = ? or 1 = 1', $builder->toSql()); - $this->assertEquals([0 => 1], $builder->getBindings()); - } - - - public function testUnions(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1); - $builder->union($this->getBuilder()->select('*')->from('users')->where('id', '=', 2)); - $this->assertEquals('select * from "users" where "id" = ? union select * from "users" where "id" = ?', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 2], $builder->getBindings()); - - $builder = $this->getMySqlBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1); - $builder->union($this->getMySqlBuilder()->select('*')->from('users')->where('id', '=', 2)); - $this->assertEquals('(select * from `users` where `id` = ?) union (select * from `users` where `id` = ?)', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 2], $builder->getBindings()); - } - - - public function testUnionAlls(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1); - $builder->unionAll($this->getBuilder()->select('*')->from('users')->where('id', '=', 2)); - $this->assertEquals('select * from "users" where "id" = ? union all select * from "users" where "id" = ?', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 2], $builder->getBindings()); - } - - - public function testMultipleUnions(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1); - $builder->union($this->getBuilder()->select('*')->from('users')->where('id', '=', 2)); - $builder->union($this->getBuilder()->select('*')->from('users')->where('id', '=', 3)); - $this->assertEquals('select * from "users" where "id" = ? union select * from "users" where "id" = ? union select * from "users" where "id" = ?', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 2, 2 => 3], $builder->getBindings()); - } - - - public function testMultipleUnionAlls(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1); - $builder->unionAll($this->getBuilder()->select('*')->from('users')->where('id', '=', 2)); - $builder->unionAll($this->getBuilder()->select('*')->from('users')->where('id', '=', 3)); - $this->assertEquals('select * from "users" where "id" = ? union all select * from "users" where "id" = ? union all select * from "users" where "id" = ?', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 2, 2 => 3], $builder->getBindings()); - } - - - public function testUnionOrderBys(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1); - $builder->union($this->getBuilder()->select('*')->from('users')->where('id', '=', 2)); - $builder->orderBy('id', 'desc'); - $this->assertEquals('select * from "users" where "id" = ? union select * from "users" where "id" = ? order by "id" desc', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 2], $builder->getBindings()); - } - - - public function testUnionLimitsAndOffsets(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users'); - $builder->union($this->getBuilder()->select('*')->from('dogs')); - $builder->skip(5)->take(10); - $this->assertEquals('select * from "users" union select * from "dogs" limit 10 offset 5', $builder->toSql()); - } - - - public function testMySqlUnionOrderBys(): void - { - $builder = $this->getMySqlBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1); - $builder->union($this->getMySqlBuilder()->select('*')->from('users')->where('id', '=', 2)); - $builder->orderBy('id', 'desc'); - $this->assertEquals('(select * from `users` where `id` = ?) union (select * from `users` where `id` = ?) order by `id` desc', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 2], $builder->getBindings()); - } - - - public function testMySqlUnionLimitsAndOffsets(): void - { - $builder = $this->getMySqlBuilder(); - $builder->select('*')->from('users'); - $builder->union($this->getMySqlBuilder()->select('*')->from('dogs')); - $builder->skip(5)->take(10); - $this->assertEquals('(select * from `users`) union (select * from `dogs`) limit 10 offset 5', $builder->toSql()); - } - - - public function testSubSelectWhereIns(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->whereIn('id', function($q) - { - $q->select('id')->from('users')->where('age', '>', 25)->take(3); - }); - $this->assertEquals('select * from "users" where "id" in (select "id" from "users" where "age" > ? limit 3)', $builder->toSql()); - $this->assertEquals([25], $builder->getBindings()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->whereNotIn('id', function($q) - { - $q->select('id')->from('users')->where('age', '>', 25)->take(3); - }); - $this->assertEquals('select * from "users" where "id" not in (select "id" from "users" where "age" > ? limit 3)', $builder->toSql()); - $this->assertEquals([25], $builder->getBindings()); - } - - - public function testBasicWhereNulls(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->whereNull('id'); - $this->assertEquals('select * from "users" where "id" is null', $builder->toSql()); - $this->assertEquals([], $builder->getBindings()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '=', 1)->orWhereNull('id'); - $this->assertEquals('select * from "users" where "id" = ? or "id" is null', $builder->toSql()); - $this->assertEquals([0 => 1], $builder->getBindings()); - } - - - public function testBasicWhereNotNulls(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->whereNotNull('id'); - $this->assertEquals('select * from "users" where "id" is not null', $builder->toSql()); - $this->assertEquals([], $builder->getBindings()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', '>', 1)->orWhereNotNull('id'); - $this->assertEquals('select * from "users" where "id" > ? or "id" is not null', $builder->toSql()); - $this->assertEquals([0 => 1], $builder->getBindings()); - } - - - public function testGroupBys(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->groupBy('id', 'email'); - $this->assertEquals('select * from "users" group by "id", "email"', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->groupBy(['id', 'email']); - $this->assertEquals('select * from "users" group by "id", "email"', $builder->toSql()); - } - - - public function testOrderBys(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->orderBy('email')->orderBy('age', 'desc'); - $this->assertEquals('select * from "users" order by "email" asc, "age" desc', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->orderBy('email')->orderByRaw('"age" ? desc', ['foo']); - $this->assertEquals('select * from "users" order by "email" asc, "age" ? desc', $builder->toSql()); - $this->assertEquals(['foo'], $builder->getBindings()); - } - - - public function testHavings(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->having('email', '>', 1); - $this->assertEquals('select * from "users" having "email" > ?', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users') - ->orHaving('email', '=', 'test@example.com') - ->orHaving('email', '=', 'test2@example.com'); - $this->assertEquals('select * from "users" having "email" = ? or "email" = ?', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->groupBy('email')->having('email', '>', 1); - $this->assertEquals('select * from "users" group by "email" having "email" > ?', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('email as foo_email')->from('users')->having('foo_email', '>', 1); - $this->assertEquals('select "email" as "foo_email" from "users" having "foo_email" > ?', $builder->toSql()); - } - - - public function testRawHavings(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->havingRaw('user_foo < user_bar'); - $this->assertEquals('select * from "users" having user_foo < user_bar', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->having('baz', '=', 1)->orHavingRaw('user_foo < user_bar'); - $this->assertEquals('select * from "users" having "baz" = ? or user_foo < user_bar', $builder->toSql()); - } - - - public function testLimitsAndOffsets(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->offset(5)->limit(10); - $this->assertEquals('select * from "users" limit 10 offset 5', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->skip(5)->take(10); - $this->assertEquals('select * from "users" limit 10 offset 5', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->skip(-5)->take(10); - $this->assertEquals('select * from "users" limit 10 offset 0', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->forPage(2, 15); - $this->assertEquals('select * from "users" limit 15 offset 15', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->forPage(-2, 15); - $this->assertEquals('select * from "users" limit 15 offset 0', $builder->toSql()); - } - - - public function testWhereShortcut(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('id', 1)->orWhere('name', 'foo'); - $this->assertEquals('select * from "users" where "id" = ? or "name" = ?', $builder->toSql()); - $this->assertEquals([0 => 1, 1 => 'foo'], $builder->getBindings()); - } - - - public function testNestedWheres(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('email', '=', 'foo')->orWhere(function($q) - { - $q->where('name', '=', 'bar')->where('age', '=', 25); - }); - $this->assertEquals('select * from "users" where "email" = ? or ("name" = ? and "age" = ?)', $builder->toSql()); - $this->assertEquals([0 => 'foo', 1 => 'bar', 2 => 25], $builder->getBindings()); - } - - - public function testFullSubSelects(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('email', '=', 'foo')->orWhere('id', '=', function($q) - { - $q->select(new Raw('max(id)'))->from('users')->where('email', '=', 'bar'); - }); - - $this->assertEquals('select * from "users" where "email" = ? or "id" = (select max(id) from "users" where "email" = ?)', $builder->toSql()); - $this->assertEquals([0 => 'foo', 1 => 'bar'], $builder->getBindings()); - } - - - public function testWhereExists(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('orders')->whereExists(function($q) - { - $q->select('*')->from('products')->where('products.id', '=', new Raw('"orders"."id"')); - }); - $this->assertEquals('select * from "orders" where exists (select * from "products" where "products"."id" = "orders"."id")', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('orders')->whereNotExists(function($q) - { - $q->select('*')->from('products')->where('products.id', '=', new Raw('"orders"."id"')); - }); - $this->assertEquals('select * from "orders" where not exists (select * from "products" where "products"."id" = "orders"."id")', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('orders')->where('id', '=', 1)->orWhereExists(function($q) - { - $q->select('*')->from('products')->where('products.id', '=', new Raw('"orders"."id"')); - }); - $this->assertEquals('select * from "orders" where "id" = ? or exists (select * from "products" where "products"."id" = "orders"."id")', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('orders')->where('id', '=', 1)->orWhereNotExists(function($q) - { - $q->select('*')->from('products')->where('products.id', '=', new Raw('"orders"."id"')); - }); - $this->assertEquals('select * from "orders" where "id" = ? or not exists (select * from "products" where "products"."id" = "orders"."id")', $builder->toSql()); - } - - - public function testBasicJoins(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->join('contacts', 'users.id', '=', 'contacts.id')->leftJoin('photos', 'users.id', '=', 'photos.id'); - $this->assertEquals('select * from "users" inner join "contacts" on "users"."id" = "contacts"."id" left join "photos" on "users"."id" = "photos"."id"', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->leftJoinWhere('photos', 'users.id', '=', 'bar')->joinWhere('photos', 'users.id', '=', 'foo'); - $this->assertEquals('select * from "users" left join "photos" on "users"."id" = ? inner join "photos" on "users"."id" = ?', $builder->toSql()); - $this->assertEquals(['bar', 'foo'], $builder->getBindings()); - } - - - public function testComplexJoin(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->join('contacts', function($j) - { - $j->on('users.id', '=', 'contacts.id')->orOn('users.name', '=', 'contacts.name'); - }); - $this->assertEquals('select * from "users" inner join "contacts" on "users"."id" = "contacts"."id" or "users"."name" = "contacts"."name"', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->join('contacts', function($j) - { - $j->where('users.id', '=', 'foo')->orWhere('users.name', '=', 'bar'); - }); - $this->assertEquals('select * from "users" inner join "contacts" on "users"."id" = ? or "users"."name" = ?', $builder->toSql()); - $this->assertEquals(['foo', 'bar'], $builder->getBindings()); - - // Run the assertions again - $this->assertEquals('select * from "users" inner join "contacts" on "users"."id" = ? or "users"."name" = ?', $builder->toSql()); - $this->assertEquals(['foo', 'bar'], $builder->getBindings()); - } - - public function testJoinWhereNull(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->join('contacts', function($j) - { - $j->on('users.id', '=', 'contacts.id')->whereNull('contacts.deleted_at'); - }); - $this->assertEquals('select * from "users" inner join "contacts" on "users"."id" = "contacts"."id" and "contacts"."deleted_at" is null', $builder->toSql()); - } - - public function testRawExpressionsInSelect(): void - { - $builder = $this->getBuilder(); - $builder->select(new Raw('substr(foo, 6)'))->from('users'); - $this->assertEquals('select substr(foo, 6) from "users"', $builder->toSql()); - } - - - public function testFindReturnsFirstResultByID(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select * from "users" where "id" = ? limit 1', [1] - )->andReturn([['foo' => 'bar']]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar']])->andReturnUsing(function($query, $results) { return $results; }); - $results = $builder->from('users')->find(1); - $this->assertEquals(['foo' => 'bar'], $results); - } - - - public function testFirstMethodReturnsFirstResult(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select * from "users" where "id" = ? limit 1', [1] - )->andReturn([['foo' => 'bar']]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar']])->andReturnUsing(function($query, $results) { return $results; }); - $results = $builder->from('users')->where('id', '=', 1)->first(); - $this->assertEquals(['foo' => 'bar'], $results); - } - - - public function testListMethodsGetsArrayOfColumnValues(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->andReturn([['foo' => 'bar'], ['foo' => 'baz']]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar'], ['foo' => 'baz']] - )->andReturnUsing(function($query, $results) - { - return $results; - }); - $results = $builder->from('users')->where('id', '=', 1)->pluck('foo'); - $this->assertEquals(['bar', 'baz'], $results); - - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->andReturn( - [['id' => 1, 'foo' => 'bar'], ['id' => 10, 'foo' => 'baz']] - ); - $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['id' => 1, 'foo' => 'bar'], ['id' => 10, 'foo' => 'baz']] - )->andReturnUsing(function($query, $results) - { - return $results; - }); - $results = $builder->from('users')->where('id', '=', 1)->pluck('foo', 'id'); - $this->assertEquals([1 => 'bar', 10 => 'baz'], $results); - } - - - public function testImplode(): void - { - // Test without glue. - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->andReturn([['foo' => 'bar'], ['foo' => 'baz']]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar'], ['foo' => 'baz']] - )->andReturnUsing(function($query, $results) - { - return $results; - }); - $results = $builder->from('users')->where('id', '=', 1)->implode('foo'); - $this->assertEquals('barbaz', $results); - - // Test with glue. - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->andReturn([['foo' => 'bar'], ['foo' => 'baz']]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar'], ['foo' => 'baz']] - )->andReturnUsing(function($query, $results) - { - return $results; - }); - $results = $builder->from('users')->where('id', '=', 1)->implode('foo', ','); - $this->assertEquals('bar,baz', $results); - } - - - public function testPaginateCorrectlyCreatesPaginatorInstance(): void - { - $connection = m::mock(ConnectionInterface::class); - $grammar = m::mock(Grammar::class); - $processor = m::mock(Processor::class); - $builder = $this->getMock(Builder::class, ['getPaginationCount', 'forPage', 'get'], [$connection, $grammar, $processor] - ); - $paginator = m::mock(Factory::class); - $paginator->shouldReceive('getCurrentPage')->once()->andReturn(1); - $connection->shouldReceive('getPaginator')->once()->andReturn($paginator); - $builder->expects($this->once())->method('forPage')->with($this->equalTo(1), $this->equalTo(15))->willReturn( - $builder - ); - $builder->expects($this->once())->method('get')->with($this->equalTo(['*']))->willReturn(['foo']); - $builder->expects($this->once())->method('getPaginationCount')->willReturn(10); - $paginator->shouldReceive('make')->once()->with(['foo'], 10, 15)->andReturn(['results']); - - $this->assertEquals(['results'], $builder->paginate(15, ['*'])); - } - - - public function testPaginateCorrectlyCreatesPaginatorInstanceForGroupedQuery(): void - { - $connection = m::mock(ConnectionInterface::class); - $grammar = m::mock(Grammar::class); - $processor = m::mock(Processor::class); - $builder = $this->getMock(Builder::class, ['get'], [$connection, $grammar, $processor]); - $paginator = m::mock(Factory::class); - $paginator->shouldReceive('getCurrentPage')->once()->andReturn(2); - $connection->shouldReceive('getPaginator')->once()->andReturn($paginator); - $builder->expects($this->once())->method('get')->with($this->equalTo(['*']))->willReturn( - ['foo', 'bar', 'baz'] - ); - $paginator->shouldReceive('make')->once()->with(['baz'], 3, 2)->andReturn(['results']); - - $this->assertEquals(['results'], $builder->groupBy('foo')->paginate(2, ['*'])); - } - - - public function testGetPaginationCountGetsResultCount(): void - { - unset($_SERVER['orders']); - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', [] - )->andReturn([['aggregate' => 1]]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($query, $results) - { - $_SERVER['orders'] = $query->orders; - return $results; - }); - $results = $builder->from('users')->orderBy('foo', 'desc')->getPaginationCount(); - - $this->assertNull($_SERVER['orders']); - unset($_SERVER['orders']); - - $this->assertEquals([0 => ['column' => 'foo', 'direction' => 'desc']], $builder->orders); - $this->assertEquals(1, $results); - } - - - public function testQuickPaginateCorrectlyCreatesPaginatorInstance(): void - { - $connection = m::mock(ConnectionInterface::class); - $grammar = m::mock(Grammar::class); - $processor = m::mock(Processor::class); - $builder = $this->getMock(Builder::class, ['skip', 'take', 'get'], [$connection, $grammar, $processor]); - $paginator = m::mock(Factory::class); - $paginator->shouldReceive('getCurrentPage')->once()->andReturn(1); - $connection->shouldReceive('getPaginator')->once()->andReturn($paginator); - $builder->expects($this->once())->method('skip')->with($this->equalTo(0))->willReturn($builder); - $builder->expects($this->once())->method('take')->with($this->equalTo(16))->willReturn($builder); - $builder->expects($this->once())->method('get')->with($this->equalTo(['*']))->willReturn(['foo']); - $paginator->shouldReceive('make')->once()->with(['foo'], 15)->andReturn(['results']); - - $this->assertEquals(['results'], $builder->simplePaginate(15, ['*'])); - } - - -public function testValueMethodReturnsSingleColumn(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select "foo" from "users" where "id" = ? limit 1', [1] - )->andReturn([['foo' => 'bar']]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar']])->andReturn( - [['foo' => 'bar']] - ); - $results = $builder->from('users')->where('id', '=', 1)->value('foo'); - $this->assertEquals('bar', $results); - } - - - public function testAggregateFunctions(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', [] - )->andReturn([['aggregate' => 1]]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; }); - $results = $builder->from('users')->count(); - $this->assertEquals(1, $results); - - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users" limit 1', [] - )->andReturn([['aggregate' => 1]]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; }); - $results = $builder->from('users')->exists(); - $this->assertTrue($results); - - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select max("id") as aggregate from "users"', [] - )->andReturn([['aggregate' => 1]]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; }); - $results = $builder->from('users')->max('id'); - $this->assertEquals(1, $results); - - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select min("id") as aggregate from "users"', [] - )->andReturn([['aggregate' => 1]]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; }); - $results = $builder->from('users')->min('id'); - $this->assertEquals(1, $results); - - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select sum("id") as aggregate from "users"', [] - )->andReturn([['aggregate' => 1]]); - $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; }); - $results = $builder->from('users')->sum('id'); - $this->assertEquals(1, $results); - } - - - public function testAggregateResetFollowedByGet(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', [] - )->andReturn([['aggregate' => 1]]); - $builder->getConnection()->shouldReceive('select')->once()->with('select sum("id") as aggregate from "users"', [] - )->andReturn([['aggregate' => 2]]); - $builder->getConnection()->shouldReceive('select')->once()->with('select "column1", "column2" from "users"', [])->andReturn( - [['column1' => 'foo', 'column2' => 'bar']] - ); - $builder->getProcessor()->shouldReceive('processSelect')->andReturnUsing(function($builder, $results) { return $results; }); - $builder->from('users')->select('column1', 'column2'); - $count = $builder->count(); - $this->assertEquals(1, $count); - $sum = $builder->sum('id'); - $this->assertEquals(2, $sum); - $result = $builder->get(); - $this->assertEquals([['column1' => 'foo', 'column2' => 'bar']], $result); - } - - - public function testAggregateResetFollowedBySelectGet(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select count("column1") as aggregate from "users"', [] - )->andReturn([['aggregate' => 1]]); - $builder->getConnection()->shouldReceive('select')->once()->with('select "column2", "column3" from "users"', [])->andReturn( - [['column2' => 'foo', 'column3' => 'bar']] - ); - $builder->getProcessor()->shouldReceive('processSelect')->andReturnUsing(function($builder, $results) { return $results; }); - $builder->from('users'); - $count = $builder->count('column1'); - $this->assertEquals(1, $count); - $result = $builder->select('column2', 'column3')->get(); - $this->assertEquals([['column2' => 'foo', 'column3' => 'bar']], $result); - } - - - public function testAggregateResetFollowedByGetWithColumns(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select count("column1") as aggregate from "users"', [] - )->andReturn([['aggregate' => 1]]); - $builder->getConnection()->shouldReceive('select')->once()->with('select "column2", "column3" from "users"', [])->andReturn( - [['column2' => 'foo', 'column3' => 'bar']] - ); - $builder->getProcessor()->shouldReceive('processSelect')->andReturnUsing(function($builder, $results) { return $results; }); - $builder->from('users'); - $count = $builder->count('column1'); - $this->assertEquals(1, $count); - $result = $builder->get(['column2', 'column3']); - $this->assertEquals([['column2' => 'foo', 'column3' => 'bar']], $result); - } - - - public function testInsertMethod(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('insert')->once()->with('insert into "users" ("email") values (?)', ['foo'] - )->andReturn(true); - $result = $builder->from('users')->insert(['email' => 'foo']); - $this->assertTrue($result); - } - - - public function testSQLiteMultipleInserts(): void - { - $builder = $this->getSQLiteBuilder(); - $builder->getConnection()->shouldReceive('insert')->once()->with('insert into "users" ("email", "name") select ? as "email", ? as "name" union select ? as "email", ? as "name"', ['foo', 'taylor', 'bar', 'dayle'] - )->andReturn(true); - $result = $builder->from('users')->insert( - [['email' => 'foo', 'name' => 'taylor'], ['email' => 'bar', 'name' => 'dayle']] - ); - $this->assertTrue($result); - } - - - public function testInsertGetIdMethod(): void - { - $builder = $this->getBuilder(); - $builder->getProcessor()->shouldReceive('processInsertGetId')->once()->with($builder, 'insert into "users" ("email") values (?)', ['foo'], 'id')->andReturn(1); - $result = $builder->from('users')->insertGetId(['email' => 'foo'], 'id'); - $this->assertEquals(1, $result); - } - - - public function testInsertGetIdMethodRemovesExpressions(): void - { - $builder = $this->getBuilder(); - $builder->getProcessor()->shouldReceive('processInsertGetId')->once()->with($builder, 'insert into "users" ("email", "bar") values (?, bar)', ['foo'], 'id')->andReturn(1); - $result = $builder->from('users')->insertGetId( - ['email' => 'foo', 'bar' => new Illuminate\Database\Query\Expression('bar')], 'id'); - $this->assertEquals(1, $result); - } - - - public function testInsertMethodRespectsRawBindings(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('insert')->once()->with('insert into "users" ("email") values (CURRENT TIMESTAMP)', [] - )->andReturn(true); - $result = $builder->from('users')->insert(['email' => new Raw('CURRENT TIMESTAMP')]); - $this->assertTrue($result); - } - - - public function testUpdateMethod(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('update')->once()->with('update "users" set "email" = ?, "name" = ? where "id" = ?', ['foo', 'bar', 1] - )->andReturn(1); - $result = $builder->from('users')->where('id', '=', 1)->update(['email' => 'foo', 'name' => 'bar']); - $this->assertEquals(1, $result); - - $builder = $this->getMySqlBuilder(); - $builder->getConnection()->shouldReceive('update')->once()->with('update `users` set `email` = ?, `name` = ? where `id` = ? order by `foo` desc limit 5', ['foo', 'bar', 1] - )->andReturn(1); - $result = $builder->from('users')->where('id', '=', 1)->orderBy('foo', 'desc')->limit(5)->update( - ['email' => 'foo', 'name' => 'bar'] - ); - $this->assertEquals(1, $result); - } - - - public function testUpdateMethodWithJoins(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('update')->once()->with('update "users" inner join "orders" on "users"."id" = "orders"."user_id" set "email" = ?, "name" = ? where "users"."id" = ?', ['foo', 'bar', 1] - )->andReturn(1); - $result = $builder->from('users')->join('orders', 'users.id', '=', 'orders.user_id')->where('users.id', '=', 1)->update( - ['email' => 'foo', 'name' => 'bar'] - ); - $this->assertEquals(1, $result); - } - - - public function testUpdateMethodWithoutJoinsOnPostgres(): void - { - $builder = $this->getPostgresBuilder(); - $builder->getConnection()->shouldReceive('update')->once()->with('update "users" set "email" = ?, "name" = ? where "id" = ?', ['foo', 'bar', 1] - )->andReturn(1); - $result = $builder->from('users')->where('id', '=', 1)->update(['email' => 'foo', 'name' => 'bar']); - $this->assertEquals(1, $result); - } - - - public function testUpdateMethodWithJoinsOnPostgres(): void - { - $builder = $this->getPostgresBuilder(); - $builder->getConnection()->shouldReceive('update')->once()->with('update "users" set "email" = ?, "name" = ? from "orders" where "users"."id" = ? and "users"."id" = "orders"."user_id"', ['foo', 'bar', 1] - )->andReturn(1); - $result = $builder->from('users')->join('orders', 'users.id', '=', 'orders.user_id')->where('users.id', '=', 1)->update( - ['email' => 'foo', 'name' => 'bar'] - ); - $this->assertEquals(1, $result); - } - - - public function testUpdateMethodRespectsRaw(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('update')->once()->with('update "users" set "email" = foo, "name" = ? where "id" = ?', ['bar', 1] - )->andReturn(1); - $result = $builder->from('users')->where('id', '=', 1)->update(['email' => new Raw('foo'), 'name' => 'bar']); - $this->assertEquals(1, $result); - } - - - public function testDeleteMethod(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('delete')->once()->with('delete from "users" where "email" = ?', ['foo'] - )->andReturn(1); - $result = $builder->from('users')->where('email', '=', 'foo')->delete(); - $this->assertEquals(1, $result); - - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('delete')->once()->with('delete from "users" where "id" = ?', [1])->andReturn(1); - $result = $builder->from('users')->delete(1); - $this->assertEquals(1, $result); - } - - - public function testDeleteWithJoinMethod(): void - { - $builder = $this->getMySqlBuilder(); - $builder->getConnection()->shouldReceive('delete')->once()->with('delete `users` from `users` inner join `contacts` on `users`.`id` = `contacts`.`id` where `email` = ?', ['foo'] - )->andReturn(1); - $result = $builder->from('users')->join('contacts', 'users.id', '=', 'contacts.id')->where('email', '=', 'foo')->delete(); - $this->assertEquals(1, $result); - - $builder = $this->getMySqlBuilder(); - $builder->getConnection()->shouldReceive('delete')->once()->with('delete `users` from `users` inner join `contacts` on `users`.`id` = `contacts`.`id` where `id` = ?', [1] - )->andReturn(1); - $result = $builder->from('users')->join('contacts', 'users.id', '=', 'contacts.id')->delete(1); - $this->assertEquals(1, $result); - } - - - public function testTruncateMethod(): void - { - $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('statement')->once()->with('truncate "users"', []); - $builder->from('users')->truncate(); - - $sqlite = new Illuminate\Database\Query\Grammars\SQLiteGrammar; - $builder = $this->getBuilder(); - $builder->from('users'); - $this->assertEquals([ - 'delete from sqlite_sequence where name = ?' => ['users'], - 'delete from "users"' => [], - ], $sqlite->compileTruncate($builder)); - } - - - public function testPostgresInsertGetId(): void - { - $builder = $this->getPostgresBuilder(); - $builder->getProcessor()->shouldReceive('processInsertGetId')->once()->with($builder, 'insert into "users" ("email") values (?) returning "id"', ['foo'], 'id')->andReturn(1); - $result = $builder->from('users')->insertGetId(['email' => 'foo'], 'id'); - $this->assertEquals(1, $result); - } - - - public function testMySqlWrapping(): void - { - $builder = $this->getMySqlBuilder(); - $builder->select('*')->from('users'); - $this->assertEquals('select * from `users`', $builder->toSql()); - } - - - public function testSQLiteOrderBy(): void - { - $builder = $this->getSQLiteBuilder(); - $builder->select('*')->from('users')->orderBy('email', 'desc'); - $this->assertEquals('select * from "users" order by "email" desc', $builder->toSql()); - } - - - public function testSqlServerLimitsAndOffsets(): void - { - $builder = $this->getSqlServerBuilder(); - $builder->select('*')->from('users')->take(10); - $this->assertEquals('select top 10 * from [users]', $builder->toSql()); - - $builder = $this->getSqlServerBuilder(); - $builder->select('*')->from('users')->skip(10); - $this->assertEquals('select * from (select *, row_number() over (order by (select 0)) as row_num from [users]) as temp_table where row_num >= 11', $builder->toSql()); - - $builder = $this->getSqlServerBuilder(); - $builder->select('*')->from('users')->skip(10)->take(10); - $this->assertEquals('select * from (select *, row_number() over (order by (select 0)) as row_num from [users]) as temp_table where row_num between 11 and 20', $builder->toSql()); - - $builder = $this->getSqlServerBuilder(); - $builder->select('*')->from('users')->skip(10)->take(10)->orderBy('email', 'desc'); - $this->assertEquals('select * from (select *, row_number() over (order by [email] desc) as row_num from [users]) as temp_table where row_num between 11 and 20', $builder->toSql()); - } - - - public function testMergeWheresCanMergeWheresAndBindings(): void - { - $builder = $this->getBuilder(); - $builder->wheres = ['foo']; - $builder->mergeWheres(['wheres'], [12 => 'foo', 13 => 'bar']); - $this->assertEquals(['foo', 'wheres'], $builder->wheres); - $this->assertEquals(['foo', 'bar'], $builder->getBindings()); - } - - - public function testProvidingNullOrFalseAsSecondParameterBuildsCorrectly(): void - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('foo', null); - $this->assertEquals('select * from "users" where "foo" is null', $builder->toSql()); - } - - - public function testDynamicWhere(): void - { - $method = 'whereFooBarAndBazOrQux'; - $parameters = ['corge', 'waldo', 'fred']; - $builder = m::mock(Builder::class)->makePartial(); - - $builder->shouldReceive('where')->with('foo_bar', '=', $parameters[0], 'and')->once()->andReturn($builder); - $builder->shouldReceive('where')->with('baz', '=', $parameters[1], 'and')->once()->andReturn($builder); - $builder->shouldReceive('where')->with('qux', '=', $parameters[2], 'or')->once()->andReturn($builder); - - $this->assertEquals($builder, $builder->dynamicWhere($method, $parameters)); - } - - - public function testDynamicWhereIsNotGreedy(): void - { - $method = 'whereIosVersionAndAndroidVersionOrOrientation'; - $parameters = ['6.1', '4.2', 'Vertical']; - $builder = m::mock(Builder::class)->makePartial(); - - $builder->shouldReceive('where')->with('ios_version', '=', '6.1', 'and')->once()->andReturn($builder); - $builder->shouldReceive('where')->with('android_version', '=', '4.2', 'and')->once()->andReturn($builder); - $builder->shouldReceive('where')->with('orientation', '=', 'Vertical', 'or')->once()->andReturn($builder); - - $builder->dynamicWhere($method, $parameters); - } - - - public function testCallTriggersDynamicWhere(): void - { - $builder = $this->getBuilder(); - - $this->assertEquals($builder, $builder->whereFooAndBar('baz', 'qux')); - $this->assertCount(2, $builder->wheres); - } - - - public function testBuilderThrowsExpectedExceptionWithUndefinedMethod(): void - { - $this->expectException(BadMethodCallException::class); - $builder = $this->getBuilder(); - - $builder->noValidMethodHere(); - } - - - public function setupCacheTestQuery($cache, $driver): Builder - { - $connection = m::mock(ConnectionInterface::class); - $connection->shouldReceive('getName')->andReturn('connection_name'); - $connection->shouldReceive('getCacheManager')->once()->andReturn($cache); - $cache->shouldReceive('driver')->once()->andReturn($driver); - $grammar = new Illuminate\Database\Query\Grammars\Grammar; - $processor = m::mock(Processor::class); - - $builder = $this->getMock(Builder::class, ['getFresh'], [$connection, $grammar, $processor]); - $builder->expects($this->once())->method('getFresh')->with($this->equalTo(['*']))->willReturn( - ['results'] - ); - return $builder->select('*')->from('users')->where('email', 'foo@bar.com'); - } - - - public function testMySqlLock(): void - { - $builder = $this->getMySqlBuilder(); - $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock(); - $this->assertEquals('select * from `foo` where `bar` = ? for update', $builder->toSql()); - $this->assertEquals(['baz'], $builder->getBindings()); - - $builder = $this->getMySqlBuilder(); - $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock(false); - $this->assertEquals('select * from `foo` where `bar` = ? lock in share mode', $builder->toSql()); - $this->assertEquals(['baz'], $builder->getBindings()); - } - - - public function testPostgresLock(): void - { - $builder = $this->getPostgresBuilder(); - $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock(); - $this->assertEquals('select * from "foo" where "bar" = ? for update', $builder->toSql()); - $this->assertEquals(['baz'], $builder->getBindings()); - - $builder = $this->getPostgresBuilder(); - $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock(false); - $this->assertEquals('select * from "foo" where "bar" = ? for share', $builder->toSql()); - $this->assertEquals(['baz'], $builder->getBindings()); - } - - - public function testSqlServerLock(): void - { - $builder = $this->getSqlServerBuilder(); - $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock(); - $this->assertEquals('select * from [foo] with(rowlock,updlock,holdlock) where [bar] = ?', $builder->toSql()); - $this->assertEquals(['baz'], $builder->getBindings()); - - $builder = $this->getSqlServerBuilder(); - $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock(false); - $this->assertEquals('select * from [foo] with(rowlock,holdlock) where [bar] = ?', $builder->toSql()); - $this->assertEquals(['baz'], $builder->getBindings()); - } - - - public function testBindingOrder(): void - { - $expectedSql = 'select * from "users" inner join "othertable" on "bar" = ? where "registered" = ? group by "city" having "population" > ? order by match ("foo") against(?)'; - $expectedBindings = ['foo', 1, 3, 'bar']; - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->join('othertable', function($join) { $join->where('bar', '=', 'foo'); })->where('registered', 1)->groupBy('city')->having('population', '>', 3)->orderByRaw('match ("foo") against(?)', ['bar'] - ); - $this->assertEquals($expectedSql, $builder->toSql()); - $this->assertEquals($expectedBindings, $builder->getBindings()); - - // order of statements reversed - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->orderByRaw('match ("foo") against(?)', ['bar'])->having('population', '>', 3)->groupBy('city')->where('registered', 1)->join('othertable', function($join) { $join->where('bar', '=', 'foo'); }); - $this->assertEquals($expectedSql, $builder->toSql()); - $this->assertEquals($expectedBindings, $builder->getBindings()); - } - - - public function testAddBindingWithArrayMergesBindings(): void - { - $builder = $this->getBuilder(); - $builder->addBinding(['foo', 'bar']); - $builder->addBinding(['baz']); - $this->assertEquals(['foo', 'bar', 'baz'], $builder->getBindings()); - } - - - public function testAddBindingWithArrayMergesBindingsInCorrectOrder(): void - { - $builder = $this->getBuilder(); - $builder->addBinding(['bar', 'baz'], 'having'); - $builder->addBinding(['foo'], 'where'); - $this->assertEquals(['foo', 'bar', 'baz'], $builder->getBindings()); - } - - - public function testMergeBuilders(): void - { - $builder = $this->getBuilder(); - $builder->addBinding(['foo', 'bar']); - $otherBuilder = $this->getBuilder(); - $otherBuilder->addBinding(['baz']); - $builder->mergeBindings($otherBuilder); - $this->assertEquals(['foo', 'bar', 'baz'], $builder->getBindings()); - } - - - public function testMergeBuildersBindingOrder(): void - { - $builder = $this->getBuilder(); - $builder->addBinding('foo', 'where'); - $builder->addBinding('baz', 'having'); - $otherBuilder = $this->getBuilder(); - $otherBuilder->addBinding('bar', 'where'); - $builder->mergeBindings($otherBuilder); - $this->assertEquals(['foo', 'bar', 'baz'], $builder->getBindings()); - } - - public function testChunkByIdOnArrays(): void - { - $builder = $this->getMockQueryBuilder(); - $builder->orders[] = ['column' => 'foobar', 'direction' => 'asc']; - - $chunk1 = [['someIdField' => 1], ['someIdField' => 2]]; - $chunk2 = [['someIdField' => 10], ['someIdField' => 11]]; - $chunk3 = []; - $builder->shouldReceive('forPageAfterId')->once()->with(2, 0, 'someIdField')->andReturnSelf(); - $builder->shouldReceive('forPageAfterId')->once()->with(2, 2, 'someIdField')->andReturnSelf(); - $builder->shouldReceive('forPageAfterId')->once()->with(2, 11, 'someIdField')->andReturnSelf(); - $builder->shouldReceive('get')->times(3)->andReturn($chunk1, $chunk2, $chunk3); - - $callbackAssertor = m::mock(stdClass::class); - $callbackAssertor->shouldReceive('doSomething')->once()->with($chunk1); - $callbackAssertor->shouldReceive('doSomething')->once()->with($chunk2); - $callbackAssertor->shouldReceive('doSomething')->never()->with($chunk3); - - $builder->chunkById(2, function ($results) use ($callbackAssertor) { - $callbackAssertor->doSomething($results); - }, 'someIdField'); - } - - public function testChunkPaginatesUsingIdWithLastChunkComplete(): void - { - $builder = $this->getMockQueryBuilder(); - $builder->orders[] = ['column' => 'foobar', 'direction' => 'asc']; - - $chunk1 = [(object) ['someIdField' => 1], (object) ['someIdField' => 2]]; - $chunk2 = [(object) ['someIdField' => 10], (object) ['someIdField' => 11]]; - $chunk3 = []; - $builder->shouldReceive('forPageAfterId')->once()->with(2, 0, 'someIdField')->andReturnSelf(); - $builder->shouldReceive('forPageAfterId')->once()->with(2, 2, 'someIdField')->andReturnSelf(); - $builder->shouldReceive('forPageAfterId')->once()->with(2, 11, 'someIdField')->andReturnSelf(); - $builder->shouldReceive('get')->times(3)->andReturn($chunk1, $chunk2, $chunk3); - - $callbackAssertor = m::mock(stdClass::class); - $callbackAssertor->shouldReceive('doSomething')->once()->with($chunk1); - $callbackAssertor->shouldReceive('doSomething')->once()->with($chunk2); - $callbackAssertor->shouldReceive('doSomething')->never()->with($chunk3); - - $builder->chunkById(2, function ($results) use ($callbackAssertor) { - $callbackAssertor->doSomething($results); - }, 'someIdField'); - } - - public function testChunkPaginatesUsingIdWithLastChunkPartial(): void - { - $builder = $this->getMockQueryBuilder(); - $builder->orders[] = ['column' => 'foobar', 'direction' => 'asc']; - - $chunk1 = [(object) ['someIdField' => 1], (object) ['someIdField' => 2]]; - $chunk2 = [(object) ['someIdField' => 10]]; - $builder->shouldReceive('forPageAfterId')->once()->with(2, 0, 'someIdField')->andReturnSelf(); - $builder->shouldReceive('forPageAfterId')->once()->with(2, 2, 'someIdField')->andReturnSelf(); - $builder->shouldReceive('get')->times(2)->andReturn($chunk1, $chunk2); - - $callbackAssertor = m::mock(stdClass::class); - $callbackAssertor->shouldReceive('doSomething')->once()->with($chunk1); - $callbackAssertor->shouldReceive('doSomething')->once()->with($chunk2); - - $builder->chunkById(2, function ($results) use ($callbackAssertor) { - $callbackAssertor->doSomething($results); - }, 'someIdField'); - } - - public function testChunkPaginatesUsingIdWithCountZero(): void - { - $builder = $this->getMockQueryBuilder(); - $builder->orders[] = ['column' => 'foobar', 'direction' => 'asc']; - - $chunk = []; - $builder->shouldReceive('forPageAfterId')->once()->with(0, 0, 'someIdField')->andReturnSelf(); - $builder->shouldReceive('get')->times(1)->andReturn($chunk); - - $callbackAssertor = m::mock(stdClass::class); - $callbackAssertor->shouldReceive('doSomething')->never(); - - $builder->chunkById(0, function ($results) use ($callbackAssertor) { - $callbackAssertor->doSomething($results); - }, 'someIdField'); - } - - public function testChunkPaginatesUsingIdWithAlias(): void - { - $builder = $this->getMockQueryBuilder(); - $builder->orders[] = ['column' => 'foobar', 'direction' => 'asc']; - - $chunk1 = [(object) ['table_id' => 1], (object) ['table_id' => 10]]; - $chunk2 = []; - $builder->shouldReceive('forPageAfterId')->once()->with(2, 0, 'table.id')->andReturnSelf(); - $builder->shouldReceive('forPageAfterId')->once()->with(2, 10, 'table.id')->andReturnSelf(); - $builder->shouldReceive('get')->times(2)->andReturn($chunk1, $chunk2); - - $callbackAssertor = m::mock(stdClass::class); - $callbackAssertor->shouldReceive('doSomething')->once()->with($chunk1); - $callbackAssertor->shouldReceive('doSomething')->never()->with($chunk2); - - $builder->chunkById(2, function ($results) use ($callbackAssertor) { - $callbackAssertor->doSomething($results); - }, 'table.id', 'table_id'); - } - - protected function getBuilder(): Builder - { - $grammar = new Illuminate\Database\Query\Grammars\Grammar; - $processor = m::mock(Processor::class); - return new Builder(m::mock(ConnectionInterface::class), $grammar, $processor); - } - - - protected function getPostgresBuilder(): Builder - { - $grammar = new Illuminate\Database\Query\Grammars\PostgresGrammar; - $processor = m::mock(Processor::class); - return new Builder(m::mock(ConnectionInterface::class), $grammar, $processor); - } - - - protected function getMySqlBuilder(): Builder - { - $grammar = new Illuminate\Database\Query\Grammars\MySqlGrammar; - $processor = m::mock(Processor::class); - return new Builder(m::mock(ConnectionInterface::class), $grammar, $processor); - } - - - protected function getSQLiteBuilder(): Builder - { - $grammar = new Illuminate\Database\Query\Grammars\SQLiteGrammar; - $processor = m::mock(Processor::class); - return new Builder(m::mock(ConnectionInterface::class), $grammar, $processor); - } - - - protected function getSqlServerBuilder(): Builder - { - $grammar = new Illuminate\Database\Query\Grammars\SqlServerGrammar; - $processor = m::mock(Processor::class); - return new Builder(m::mock(ConnectionInterface::class), $grammar, $processor); - } - - - protected function getMySqlBuilderWithProcessor(): Builder - { - $grammar = new Illuminate\Database\Query\Grammars\MySqlGrammar; - $processor = new Illuminate\Database\Query\Processors\MySqlProcessor; - return new Builder(m::mock(ConnectionInterface::class), $grammar, $processor); - } - - /** - * @return MockInterface|\Illuminate\Database\Query\Builder - */ - protected function getMockQueryBuilder(): MockInterface|Builder - { - return m::mock(Builder::class, [ - m::mock(ConnectionInterface::class), - new Grammar, - m::mock(Processor::class), - ])->makePartial()->shouldAllowMockingProtectedMethods(); - } - -} diff --git a/tests/Database/DatabaseSQLiteProcessorTest.php b/tests/Database/DatabaseSQLiteProcessorTest.php deleted file mode 100644 index 183ac2006..000000000 --- a/tests/Database/DatabaseSQLiteProcessorTest.php +++ /dev/null @@ -1,25 +0,0 @@ - 'id'], ['name' => 'name'], ['name' => 'email']]; - $expected = ['id', 'name', 'email']; - - $this->assertEquals($expected, $processor->processColumnListing($listing)); - - // convert listing to objects to simulate PDO::FETCH_CLASS - foreach($listing as &$row) - { - $row = (object) $row; - } - - $this->assertEquals($expected, $processor->processColumnListing($listing)); - } - -} diff --git a/tests/Database/DatabaseSQLiteSchemaGrammarTest.php b/tests/Database/DatabaseSQLiteSchemaGrammarTest.php deleted file mode 100755 index bd346fb8c..000000000 --- a/tests/Database/DatabaseSQLiteSchemaGrammarTest.php +++ /dev/null @@ -1,419 +0,0 @@ -create(); - $blueprint->increments('id'); - $blueprint->string('email'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('create table "users" ("id" integer not null primary key autoincrement, "email" varchar not null)', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->increments('id'); - $blueprint->string('email'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(2, $statements); - $expected = [ - 'alter table "users" add column "id" integer not null primary key autoincrement', - 'alter table "users" add column "email" varchar not null', - ]; - $this->assertEquals($expected, $statements); - } - - - public function testDropTable() - { - $blueprint = new Blueprint('users'); - $blueprint->drop(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('drop table "users"', $statements[0]); - } - - - public function testDropTableIfExists() - { - $blueprint = new Blueprint('users'); - $blueprint->dropIfExists(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('drop table if exists "users"', $statements[0]); - } - - - public function testDropUnique() - { - $blueprint = new Blueprint('users'); - $blueprint->dropUnique('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('drop index foo', $statements[0]); - } - - - public function testDropIndex() - { - $blueprint = new Blueprint('users'); - $blueprint->dropIndex('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('drop index foo', $statements[0]); - } - - - public function testRenameTable() - { - $blueprint = new Blueprint('users'); - $blueprint->rename('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" rename to "foo"', $statements[0]); - } - - - public function testAddingPrimaryKey() - { - $blueprint = new Blueprint('users'); - $blueprint->create(); - $blueprint->string('foo')->primary(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('create table "users" ("foo" varchar not null, primary key ("foo"))', $statements[0]); - } - - - public function testAddingForeignKey() - { - $blueprint = new Blueprint('users'); - $blueprint->create(); - $blueprint->string('foo')->primary(); - $blueprint->string('order_id'); - $blueprint->foreign('order_id')->references('id')->on('orders'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('create table "users" ("foo" varchar not null, "order_id" varchar not null, foreign key("order_id") references "orders"("id"), primary key ("foo"))', $statements[0]); - } - - - public function testAddingUniqueKey() - { - $blueprint = new Blueprint('users'); - $blueprint->unique('foo', 'bar'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('create unique index bar on "users" ("foo")', $statements[0]); - } - - - public function testAddingIndex() - { - $blueprint = new Blueprint('users'); - $blueprint->index(['foo', 'bar'], 'baz'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('create index baz on "users" ("foo", "bar")', $statements[0]); - } - - - public function testAddingIncrementingID() - { - $blueprint = new Blueprint('users'); - $blueprint->increments('id'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "id" integer not null primary key autoincrement', $statements[0]); - } - - - public function testAddingBigIncrementingID() - { - $blueprint = new Blueprint('users'); - $blueprint->bigIncrements('id'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "id" integer not null primary key autoincrement', $statements[0]); - } - - - public function testAddingString() - { - $blueprint = new Blueprint('users'); - $blueprint->string('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" varchar not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->string('foo', 100); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" varchar not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->string('foo', 100)->nullable()->default('bar'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" varchar null default \'bar\'', $statements[0]); - } - - - public function testAddingText() - { - $blueprint = new Blueprint('users'); - $blueprint->text('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" text not null', $statements[0]); - } - - - public function testAddingBigInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->bigInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" integer not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->bigInteger('foo', true); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" integer not null primary key autoincrement', $statements[0]); - } - - - public function testAddingInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->integer('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" integer not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->integer('foo', true); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" integer not null primary key autoincrement', $statements[0]); - } - - - public function testAddingMediumInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->mediumInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" integer not null', $statements[0]); - } - - - public function testAddingTinyInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->tinyInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" integer not null', $statements[0]); - } - - - public function testAddingSmallInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->smallInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" integer not null', $statements[0]); - } - - - public function testAddingFloat() - { - $blueprint = new Blueprint('users'); - $blueprint->float('foo', 5, 2); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" float not null', $statements[0]); - } - - - public function testAddingDouble() - { - $blueprint = new Blueprint('users'); - $blueprint->double('foo', 15, 8); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" float not null', $statements[0]); - } - - - public function testAddingDecimal() - { - $blueprint = new Blueprint('users'); - $blueprint->decimal('foo', 5, 2); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" float not null', $statements[0]); - } - - - public function testAddingBoolean() - { - $blueprint = new Blueprint('users'); - $blueprint->boolean('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" tinyint not null', $statements[0]); - } - - - public function testAddingEnum() - { - $blueprint = new Blueprint('users'); - $blueprint->enum('foo', ['bar', 'baz']); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" varchar not null', $statements[0]); - } - - - public function testAddingDate() - { - $blueprint = new Blueprint('users'); - $blueprint->date('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" date not null', $statements[0]); - } - - - public function testAddingDateTime() - { - $blueprint = new Blueprint('users'); - $blueprint->dateTime('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" datetime not null', $statements[0]); - } - - - public function testAddingTime() - { - $blueprint = new Blueprint('users'); - $blueprint->time('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" time not null', $statements[0]); - } - - - public function testAddingTimeStamp() - { - $blueprint = new Blueprint('users'); - $blueprint->timestamp('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" datetime not null', $statements[0]); - } - - - public function testAddingTimeStamps() - { - $blueprint = new Blueprint('users'); - $blueprint->timestamps(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(2, $statements); - $expected = [ - 'alter table "users" add column "created_at" datetime not null', - 'alter table "users" add column "updated_at" datetime not null', - ]; - $this->assertEquals($expected, $statements); - } - - - public function testAddingRememberToken() - { - $blueprint = new Blueprint('users'); - $blueprint->rememberToken(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "remember_token" varchar null', $statements[0]); - } - - - public function testAddingBinary() - { - $blueprint = new Blueprint('users'); - $blueprint->binary('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add column "foo" blob not null', $statements[0]); - } - - - protected function getConnection() - { - return m::mock(Connection::class); - } - - - public function getGrammar() - { - return new Illuminate\Database\Schema\Grammars\SQLiteGrammar; - } - -} diff --git a/tests/Database/DatabaseSchemaBlueprintTest.php b/tests/Database/DatabaseSchemaBlueprintTest.php deleted file mode 100755 index 93e741a94..000000000 --- a/tests/Database/DatabaseSchemaBlueprintTest.php +++ /dev/null @@ -1,61 +0,0 @@ -shouldReceive('statement')->once()->with('foo'); - $conn->shouldReceive('statement')->once()->with('bar'); - $grammar = m::mock(MySqlGrammar::class); - $blueprint = $this->getMock(Blueprint::class, ['toSql'], ['users']); - $blueprint->expects($this->once())->method('toSql')->with($this->equalTo($conn), $this->equalTo($grammar))->willReturn( - ['foo', 'bar'] - ); - - $blueprint->build($conn, $grammar); - } - - - public function testIndexDefaultNames() - { - $blueprint = new Blueprint('users'); - $blueprint->unique(['foo', 'bar']); - $commands = $blueprint->getCommands(); - $this->assertEquals('users_foo_bar_unique', $commands[0]->index); - - $blueprint = new Blueprint('users'); - $blueprint->index('foo'); - $commands = $blueprint->getCommands(); - $this->assertEquals('users_foo_index', $commands[0]->index); - } - - - public function testDropIndexDefaultNames() - { - $blueprint = new Blueprint('users'); - $blueprint->dropUnique(['foo', 'bar']); - $commands = $blueprint->getCommands(); - $this->assertEquals('users_foo_bar_unique', $commands[0]->index); - - $blueprint = new Blueprint('users'); - $blueprint->dropIndex(['foo']); - $commands = $blueprint->getCommands(); - $this->assertEquals('users_foo_index', $commands[0]->index); - } - - -} diff --git a/tests/Database/DatabaseSchemaBuilderTest.php b/tests/Database/DatabaseSchemaBuilderTest.php deleted file mode 100755 index 6d86feabb..000000000 --- a/tests/Database/DatabaseSchemaBuilderTest.php +++ /dev/null @@ -1,30 +0,0 @@ -shouldReceive('getSchemaGrammar')->andReturn($grammar); - $builder = new Builder($connection); - $grammar->shouldReceive('compileTableExists')->once()->andReturn('sql'); - $connection->shouldReceive('getTablePrefix')->once()->andReturn('prefix_'); - $connection->shouldReceive('select')->once()->with('sql', ['prefix_table'])->andReturn(['prefix_table']); - - $this->assertTrue($builder->hasTable('table')); - } - -} diff --git a/tests/Database/DatabaseSeederTest.php b/tests/Database/DatabaseSeederTest.php deleted file mode 100755 index e50ccff84..000000000 --- a/tests/Database/DatabaseSeederTest.php +++ /dev/null @@ -1,52 +0,0 @@ -setContainer($container = m::mock(Container::class)); - $output = m::mock(OutputInterface::class); - $output->shouldReceive('writeln')->once()->andReturn('foo'); - $command = m::mock(Command::class); - $command->shouldReceive('getOutput')->once()->andReturn($output); - $seeder->setCommand($command); - $container->shouldReceive('make')->once()->with('ClassName')->andReturn($child = m::mock('StdClass')); - $child->shouldReceive('setContainer')->once()->with($container)->andReturn($child); - $child->shouldReceive('setCommand')->once()->with($command)->andReturn($child); - $child->shouldReceive('run')->once(); - - $seeder->call('ClassName'); - } - - - public function testSetContainer() - { - $seeder = new Seeder; - $container = m::mock(Container::class); - $this->assertEquals($seeder->setContainer($container), $seeder); - } - - - public function testSetCommand() - { - $seeder = new Seeder; - $command = m::mock(Command::class); - $this->assertEquals($seeder->setCommand($command), $seeder); - } - -} diff --git a/tests/Database/DatabaseSoftDeletingScopeTest.php b/tests/Database/DatabaseSoftDeletingScopeTest.php deleted file mode 100644 index 144cef105..000000000 --- a/tests/Database/DatabaseSoftDeletingScopeTest.php +++ /dev/null @@ -1,122 +0,0 @@ -shouldReceive('getModel')->once()->andReturn($model = m::mock('StdClass')); - $model->shouldReceive('getQualifiedDeletedAtColumn')->once()->andReturn('table.deleted_at'); - $builder->shouldReceive('whereNull')->once()->with('table.deleted_at'); - $scope->shouldReceive('extend')->once(); - - $scope->apply($builder); - } - - - public function testScopeCanRemoveDeletedAtConstraints() - { - $scope = new Illuminate\Database\Eloquent\SoftDeletingScope; - $builder = m::mock(Builder::class); - $builder->shouldReceive('getModel')->andReturn($model = m::mock('StdClass')); - $model->shouldReceive('getQualifiedDeletedAtColumn')->andReturn('table.deleted_at'); - $builder->shouldReceive('getQuery')->andReturn($query = m::mock('StdClass')); - $query->wheres = [['type' => 'Null', 'column' => 'foo'], ['type' => 'Null', 'column' => 'table.deleted_at']]; - $scope->remove($builder); - - $this->assertEquals($query->wheres, [['type' => 'Null', 'column' => 'foo']]); - } - - - public function testForceDeleteExtension() - { - $builder = m::mock(Builder::class); - $builder->makePartial(); - $scope = new Illuminate\Database\Eloquent\SoftDeletingScope; - $scope->extend($builder); - $callback = $builder->getMacro('forceDelete'); - $givenBuilder = m::mock(Builder::class); - $givenBuilder->shouldReceive('getQuery')->andReturn($query = m::mock('StdClass')); - $query->shouldReceive('delete')->once(); - - $callback($givenBuilder); - } - - - public function testRestoreExtension() - { - $builder = m::mock(Builder::class); - $builder->makePartial(); - $scope = new Illuminate\Database\Eloquent\SoftDeletingScope; - $scope->extend($builder); - $callback = $builder->getMacro('restore'); - $givenBuilder = m::mock(Builder::class); - $givenBuilder->shouldReceive('withTrashed')->once(); - $givenBuilder->shouldReceive('getModel')->once()->andReturn($model = m::mock('StdClass')); - $model->shouldReceive('getDeletedAtColumn')->once()->andReturn('deleted_at'); - $givenBuilder->shouldReceive('update')->once()->with(['deleted_at' => null]); - - $callback($givenBuilder); - } - - - public function testWithTrashedExtension() - { - $builder = m::mock(Builder::class); - $builder->makePartial(); - $scope = m::mock('Illuminate\Database\Eloquent\SoftDeletingScope[remove]'); - $scope->extend($builder); - $callback = $builder->getMacro('withTrashed'); - $givenBuilder = m::mock(Builder::class); - $scope->shouldReceive('remove')->once()->with($givenBuilder); - $result = $callback($givenBuilder); - - $this->assertEquals($givenBuilder, $result); - } - - - public function testOnlyTrashedExtension() - { - $builder = m::mock(Builder::class); - $builder->makePartial(); - $scope = m::mock('Illuminate\Database\Eloquent\SoftDeletingScope[remove]'); - $scope->extend($builder); - $callback = $builder->getMacro('onlyTrashed'); - $givenBuilder = m::mock(Builder::class); - $scope->shouldReceive('remove')->once()->with($givenBuilder); - $givenBuilder->shouldReceive('getQuery')->andReturn($query = m::mock('StdClass')); - $givenBuilder->shouldReceive('getModel')->andReturn($model = m::mock('StdClass')); - $model->shouldReceive('getQualifiedDeletedAtColumn')->andReturn('table.deleted_at'); - $query->shouldReceive('whereNotNull')->once()->with('table.deleted_at'); - $result = $callback($givenBuilder); - - $this->assertEquals($givenBuilder, $result); - } - -} - - -class DatabaseSoftDeletingScopeBuilderStub { - public $extensions = []; - public $onDelete; - public function extend($name, $callback) - { - $this->extensions[$name] = $callback; - } - public function onDelete($callback) - { - $this->onDelete = $callback; - } -} diff --git a/tests/Database/DatabaseSoftDeletingTraitTest.php b/tests/Database/DatabaseSoftDeletingTraitTest.php deleted file mode 100644 index f3ce3e492..000000000 --- a/tests/Database/DatabaseSoftDeletingTraitTest.php +++ /dev/null @@ -1,91 +0,0 @@ -makePartial(); - $model->shouldReceive('newQuery')->andReturn($query = m::mock('StdClass')); - $query->shouldReceive('where')->once()->with('id', 1)->andReturn($query); - $query->shouldReceive('update')->once()->with(['deleted_at' => 'date-time']); - $model->delete(); - - $this->assertInstanceOf(Carbon::class, $model->deleted_at); - } - - - public function testRestore() - { - $model = m::mock('DatabaseSoftDeletingTraitStub'); - $model->makePartial(); - $model->shouldReceive('fireModelEvent')->with('restoring')->andReturn(true); - $model->shouldReceive('save')->once(); - $model->shouldReceive('fireModelEvent')->with('restored', false)->andReturn(true); - - $model->restore(); - - $this->assertNull($model->deleted_at); - } - - - public function testRestoreCancel() - { - $model = m::mock('DatabaseSoftDeletingTraitStub'); - $model->makePartial(); - $model->shouldReceive('fireModelEvent')->with('restoring')->andReturn(false); - $model->shouldReceive('save')->never(); - - $this->assertFalse($model->restore()); - } - -} - - -class DatabaseSoftDeletingTraitStub { - use Illuminate\Database\Eloquent\SoftDeletes; - public $deleted_at; - public function newQuery() - { - // - } - public function getKey() - { - return 1; - } - public function getKeyName() - { - return 'id'; - } - public function save() - { - // - } - public function delete() - { - return $this->performDeleteOnModel(); - } - public function fireModelEvent() - { - // - } - public function freshTimestamp() - { - return Carbon::now(); - } - public function fromDateTime() - { - return 'date-time'; - } -} diff --git a/tests/Database/DatabaseSqlServerSchemaGrammarTest.php b/tests/Database/DatabaseSqlServerSchemaGrammarTest.php deleted file mode 100755 index f6e01fa90..000000000 --- a/tests/Database/DatabaseSqlServerSchemaGrammarTest.php +++ /dev/null @@ -1,443 +0,0 @@ -create(); - $blueprint->increments('id'); - $blueprint->string('email'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('create table "users" ("id" int identity primary key not null, "email" nvarchar(255) not null)', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->increments('id'); - $blueprint->string('email'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "id" int identity primary key not null, "email" nvarchar(255) not null', $statements[0]); - } - - - public function testDropTable() - { - $blueprint = new Blueprint('users'); - $blueprint->drop(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('drop table "users"', $statements[0]); - } - - - public function testDropColumn() - { - $blueprint = new Blueprint('users'); - $blueprint->dropColumn('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" drop column "foo"', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->dropColumn(['foo', 'bar']); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" drop column "foo", "bar"', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->dropColumn('foo', 'bar'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" drop column "foo", "bar"', $statements[0]); - } - - - public function testDropPrimary() - { - $blueprint = new Blueprint('users'); - $blueprint->dropPrimary('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" drop constraint foo', $statements[0]); - } - - - public function testDropUnique() - { - $blueprint = new Blueprint('users'); - $blueprint->dropUnique('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('drop index foo on "users"', $statements[0]); - } - - - public function testDropIndex() - { - $blueprint = new Blueprint('users'); - $blueprint->dropIndex('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('drop index foo on "users"', $statements[0]); - } - - - public function testDropForeign() - { - $blueprint = new Blueprint('users'); - $blueprint->dropForeign('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" drop constraint foo', $statements[0]); - } - - - public function testDropTimestamps() - { - $blueprint = new Blueprint('users'); - $blueprint->dropTimestamps(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" drop column "created_at", "updated_at"', $statements[0]); - } - - - public function testRenameTable() - { - $blueprint = new Blueprint('users'); - $blueprint->rename('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('sp_rename "users", "foo"', $statements[0]); - } - - - public function testAddingPrimaryKey() - { - $blueprint = new Blueprint('users'); - $blueprint->primary('foo', 'bar'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add constraint bar primary key ("foo")', $statements[0]); - } - - - public function testAddingUniqueKey() - { - $blueprint = new Blueprint('users'); - $blueprint->unique('foo', 'bar'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('create unique index bar on "users" ("foo")', $statements[0]); - } - - - public function testAddingIndex() - { - $blueprint = new Blueprint('users'); - $blueprint->index(['foo', 'bar'], 'baz'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('create index baz on "users" ("foo", "bar")', $statements[0]); - } - - - public function testAddingIncrementingID() - { - $blueprint = new Blueprint('users'); - $blueprint->increments('id'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "id" int identity primary key not null', $statements[0]); - } - - - public function testAddingBigIncrementingID() - { - $blueprint = new Blueprint('users'); - $blueprint->bigIncrements('id'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "id" bigint identity primary key not null', $statements[0]); - } - - - public function testAddingString() - { - $blueprint = new Blueprint('users'); - $blueprint->string('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" nvarchar(255) not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->string('foo', 100); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" nvarchar(100) not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->string('foo', 100)->nullable()->default('bar'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" nvarchar(100) null default \'bar\'', $statements[0]); - } - - - public function testAddingText() - { - $blueprint = new Blueprint('users'); - $blueprint->text('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" nvarchar(max) not null', $statements[0]); - } - - - public function testAddingBigInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->bigInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" bigint not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->bigInteger('foo', true); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" bigint identity primary key not null', $statements[0]); - } - - - public function testAddingInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->integer('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" int not null', $statements[0]); - - $blueprint = new Blueprint('users'); - $blueprint->integer('foo', true); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" int identity primary key not null', $statements[0]); - } - - - public function testAddingMediumInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->mediumInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" int not null', $statements[0]); - } - - - public function testAddingTinyInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->tinyInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" tinyint not null', $statements[0]); - } - - - public function testAddingSmallInteger() - { - $blueprint = new Blueprint('users'); - $blueprint->smallInteger('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" smallint not null', $statements[0]); - } - - - public function testAddingFloat() - { - $blueprint = new Blueprint('users'); - $blueprint->float('foo', 5, 2); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" float not null', $statements[0]); - } - - - public function testAddingDouble() - { - $blueprint = new Blueprint('users'); - $blueprint->double('foo', 15, 2); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" float not null', $statements[0]); - } - - - public function testAddingDecimal() - { - $blueprint = new Blueprint('users'); - $blueprint->decimal('foo', 5, 2); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" decimal(5, 2) not null', $statements[0]); - } - - - public function testAddingBoolean() - { - $blueprint = new Blueprint('users'); - $blueprint->boolean('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" bit not null', $statements[0]); - } - - - public function testAddingEnum() - { - $blueprint = new Blueprint('users'); - $blueprint->enum('foo', ['bar', 'baz']); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" nvarchar(255) not null', $statements[0]); - } - - - public function testAddingDate() - { - $blueprint = new Blueprint('users'); - $blueprint->date('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" date not null', $statements[0]); - } - - - public function testAddingDateTime() - { - $blueprint = new Blueprint('users'); - $blueprint->dateTime('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" datetime not null', $statements[0]); - } - - - public function testAddingTime() - { - $blueprint = new Blueprint('users'); - $blueprint->time('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" time not null', $statements[0]); - } - - - public function testAddingTimeStamp() - { - $blueprint = new Blueprint('users'); - $blueprint->timestamp('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" datetime not null', $statements[0]); - } - - - public function testAddingTimeStamps() - { - $blueprint = new Blueprint('users'); - $blueprint->timestamps(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "created_at" datetime not null, "updated_at" datetime not null', $statements[0]); - } - - - public function testAddingRememberToken() - { - $blueprint = new Blueprint('users'); - $blueprint->rememberToken(); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "remember_token" nvarchar(100) null', $statements[0]); - } - - - public function testAddingBinary() - { - $blueprint = new Blueprint('users'); - $blueprint->binary('foo'); - $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); - - $this->assertCount(1, $statements); - $this->assertEquals('alter table "users" add "foo" varbinary(max) not null', $statements[0]); - } - - - protected function getConnection() - { - return m::mock(Connection::class); - } - - - public function getGrammar() - { - return new Illuminate\Database\Schema\Grammars\SqlServerGrammar; - } - -} diff --git a/tests/Database/stubs/EloquentModelNamespacedStub.php b/tests/Database/stubs/EloquentModelNamespacedStub.php deleted file mode 100755 index 39872488c..000000000 --- a/tests/Database/stubs/EloquentModelNamespacedStub.php +++ /dev/null @@ -1,7 +0,0 @@ -getEncrypter(); - $this->assertNotEquals('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $e->encrypt('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')); - $encrypted = $e->encrypt('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'); - $this->assertEquals('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $e->decrypt($encrypted)); - } - - - public function testEncryptionWithCustomCipher() - { - $e = $this->getEncrypter(); - $this->assertNotEquals('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $e->encrypt('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')); - $encrypted = $e->encrypt('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'); - $this->assertEquals('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $e->decrypt($encrypted)); - } - - public function testExceptionThrownWhenPayloadIsInvalid() - { - $this->expectException(Illuminate\Contracts\Encryption\DecryptException::class); - $this->expectExceptionMessage("The payload is invalid."); - $e = $this->getEncrypter(); - $payload = $e->encrypt('foo'); - $payload = str_shuffle((string) $payload); - $e->decrypt($payload); - } - - - protected function getEncrypter() - { - return new Encrypter(str_repeat('a', 32)); - } - -} diff --git a/tests/Events/EventsDispatcherTest.php b/tests/Events/EventsDispatcherTest.php deleted file mode 100755 index c98c29162..000000000 --- a/tests/Events/EventsDispatcherTest.php +++ /dev/null @@ -1,133 +0,0 @@ -listen( - 'foo', - function ($foo) { - $_SERVER['__event.test'] = $foo; - } - ); - $d->fire('foo', ['bar']); - $this->assertEquals('bar', $_SERVER['__event.test']); - } - - - public function testDispatchIsCanonicalAndFireDelegates() - { - $d = new Dispatcher; - $d->listen('foo', function ($x) { return 'heard:'.$x; }); - - $this->assertSame(['heard:bar'], $d->dispatch('foo', ['bar'])); - // fire() is the L4.2 alias — identical behaviour, removed at L13 swap - $this->assertSame($d->dispatch('foo', ['bar']), $d->fire('foo', ['bar'])); - // halt returns the first non-null response - $this->assertSame('heard:bar', $d->dispatch('foo', ['bar'], true)); - } - - - public function testContainerResolutionOfEventHandlers() - { - $d = new Dispatcher($container = m::mock(Container::class)); - $container->shouldReceive('make')->once()->with('FooHandler')->andReturn($handler = m::mock('StdClass')); - $handler->shouldReceive('onFooEvent')->once()->with('foo', 'bar'); - $d->listen('foo', 'FooHandler@onFooEvent'); - $d->fire('foo', ['foo', 'bar']); - } - - - public function testContainerResolutionOfEventHandlersWithDefaultMethods() - { - $d = new Dispatcher($container = m::mock(Container::class)); - $container->shouldReceive('make')->once()->with('FooHandler')->andReturn($handler = m::mock('StdClass')); - $handler->shouldReceive('handle')->once()->with('foo', 'bar'); - $d->listen('foo', 'FooHandler'); - $d->fire('foo', ['foo', 'bar']); - } - - - public function testQueuedEventsAreFired() - { - unset($_SERVER['__event.test']); - $d = new Dispatcher; - $d->queue('update', ['name' => 'taylor']); - $d->listen('update', function($name) - { - $_SERVER['__event.test'] = $name; - }); - - $this->assertFalse(isset($_SERVER['__event.test'])); - $d->flush('update'); - $this->assertEquals('taylor', $_SERVER['__event.test']); - } - - - public function testQueuedEventsCanBeForgotten() - { - $_SERVER['__event.test'] = 'unset'; - $d = new Dispatcher; - $d->queue('update', ['name' => 'taylor']); - $d->listen('update', function($name) - { - $_SERVER['__event.test'] = $name; - }); - - $d->forgetQueued(); - $d->flush('update'); - $this->assertEquals('unset', $_SERVER['__event.test']); - } - - - public function testWildcardListeners() - { - unset($_SERVER['__event.test']); - $d = new Dispatcher; - $d->listen('foo.bar', function() { $_SERVER['__event.test'] = 'regular'; }); - $d->listen('foo.*', function() { $_SERVER['__event.test'] = 'wildcard'; }); - $d->listen('bar.*', function() { $_SERVER['__event.test'] = 'nope'; }); - $d->fire('foo.bar'); - - $this->assertEquals('wildcard', $_SERVER['__event.test']); - } - - - public function testListenersCanBeRemoved() - { - unset($_SERVER['__event.test']); - $d = new Dispatcher; - $d->listen('foo', function() { $_SERVER['__event.test'] = 'foo'; }); - $d->forget('foo'); - $d->fire('foo'); - - $this->assertFalse(isset($_SERVER['__event.test'])); - } - - - public function testFiringReturnsCurrentlyFiredEvent() - { - unset($_SERVER['__event.test']); - $d = new Dispatcher; - $d->listen('foo', function() use ($d) { $_SERVER['__event.test'] = $d->firing(); $d->fire('bar'); }); - $d->listen('bar', function() use ($d) { $_SERVER['__event.test'] = $d->firing(); }); - $d->fire('foo'); - - $this->assertEquals('bar', $_SERVER['__event.test']); - } - -} diff --git a/tests/Exception/HandlerTest.php b/tests/Exception/HandlerTest.php index 024c4ab0a..4283ad1d9 100644 --- a/tests/Exception/HandlerTest.php +++ b/tests/Exception/HandlerTest.php @@ -1,6 +1,6 @@ assertEquals('Hello World', $files->get(__DIR__.'/file.txt')); - @unlink(__DIR__.'/file.txt'); - } - - - public function testPutStoresFiles() - { - $files = new Filesystem; - $files->put(__DIR__.'/file.txt', 'Hello World'); - $this->assertEquals('Hello World', file_get_contents(__DIR__.'/file.txt')); - @unlink(__DIR__.'/file.txt'); - } - - - public function testDeleteRemovesFiles() - { - file_put_contents(__DIR__.'/file.txt', 'Hello World'); - $files = new Filesystem; - $files->delete(__DIR__.'/file.txt'); - $this->assertFileDoesNotExist(__DIR__ . '/file.txt'); - @unlink(__DIR__.'/file.txt'); - } - - - public function testPrependExistingFiles() - { - $files = new Filesystem; - $files->put(__DIR__.'/file.txt', 'World'); - $files->prepend(__DIR__.'/file.txt', 'Hello '); - $this->assertEquals('Hello World', file_get_contents(__DIR__.'/file.txt')); - @unlink(__DIR__.'/file.txt'); - } - - - public function testPrependNewFiles() - { - $files = new Filesystem; - $files->prepend(__DIR__.'/file.txt', 'Hello World'); - $this->assertEquals('Hello World', file_get_contents(__DIR__.'/file.txt')); - @unlink(__DIR__.'/file.txt'); - } - - - public function testDeleteDirectory() - { - mkdir(__DIR__.'/foo'); - file_put_contents(__DIR__.'/foo/file.txt', 'Hello World'); - $files = new Filesystem; - $files->deleteDirectory(__DIR__.'/foo'); - $this->assertDirectoryDoesNotExist(__DIR__ . '/foo'); - $this->assertFileDoesNotExist(__DIR__ . '/foo/file.txt'); - } - - - public function testCleanDirectory() - { - mkdir(__DIR__.'/foo'); - file_put_contents(__DIR__.'/foo/file.txt', 'Hello World'); - $files = new Filesystem; - $files->cleanDirectory(__DIR__.'/foo'); - $this->assertDirectoryExists(__DIR__ . '/foo'); - $this->assertFileDoesNotExist(__DIR__ . '/foo/file.txt'); - @rmdir(__DIR__.'/foo'); - } - - - public function testFilesMethod() - { - mkdir(__DIR__.'/foo'); - file_put_contents(__DIR__.'/foo/1.txt', '1'); - file_put_contents(__DIR__.'/foo/2.txt', '2'); - mkdir(__DIR__.'/foo/bar'); - $files = new Filesystem; - $this->assertEquals([__DIR__.'/foo/1.txt', __DIR__.'/foo/2.txt'], $files->files(__DIR__.'/foo')); - unset($files); - @unlink(__DIR__.'/foo/1.txt'); - @unlink(__DIR__.'/foo/2.txt'); - @rmdir(__DIR__.'/foo/bar'); - @rmdir(__DIR__.'/foo'); - } - - - public function testCopyDirectoryReturnsFalseIfSourceIsntDirectory() - { - $files = new Filesystem; - $this->assertFalse($files->copyDirectory(__DIR__.'/foo/bar/baz/breeze/boom', __DIR__)); - } - - - public function testCopyDirectoryMovesEntireDirectory() - { - mkdir(__DIR__.'/tmp', 0777, true); - file_put_contents(__DIR__.'/tmp/foo.txt', ''); - file_put_contents(__DIR__.'/tmp/bar.txt', ''); - mkdir(__DIR__.'/tmp/nested', 0777, true); - file_put_contents(__DIR__.'/tmp/nested/baz.txt', ''); - - $files = new Filesystem; - $files->copyDirectory(__DIR__.'/tmp', __DIR__.'/tmp2'); - $this->assertDirectoryExists(__DIR__ . '/tmp2'); - $this->assertFileExists(__DIR__ . '/tmp2/foo.txt'); - $this->assertFileExists(__DIR__ . '/tmp2/bar.txt'); - $this->assertDirectoryExists(__DIR__ . '/tmp2/nested'); - $this->assertFileExists(__DIR__ . '/tmp2/nested/baz.txt'); - - unlink(__DIR__.'/tmp/nested/baz.txt'); - rmdir(__DIR__.'/tmp/nested'); - unlink(__DIR__.'/tmp/bar.txt'); - unlink(__DIR__.'/tmp/foo.txt'); - rmdir(__DIR__.'/tmp'); - - unlink(__DIR__.'/tmp2/nested/baz.txt'); - rmdir(__DIR__.'/tmp2/nested'); - unlink(__DIR__.'/tmp2/foo.txt'); - unlink(__DIR__.'/tmp2/bar.txt'); - rmdir(__DIR__.'/tmp2'); - } - -} diff --git a/tests/Foundation/FoundationApplicationTest.php b/tests/Foundation/FoundationApplicationTest.php index 32abff791..107d9382a 100755 --- a/tests/Foundation/FoundationApplicationTest.php +++ b/tests/Foundation/FoundationApplicationTest.php @@ -34,7 +34,7 @@ public function testCoreAliasResolvesHashByBothContractAndLegacyName() { $app = new Application; $app->registerCoreContainerAliases(); - $app->bindShared('hash', function() { return new Illuminate\Hashing\BcryptHasher; }); + $app->singleton('hash', function() { return new Illuminate\Hashing\BcryptHasher; }); $this->assertInstanceOf(Illuminate\Contracts\Hashing\Hasher::class, $app->make(Illuminate\Contracts\Hashing\Hasher::class)); // BC: the pre-migration interface name must still resolve via make()/autowiring; @@ -206,7 +206,7 @@ class ApplicationDeferredSharedServiceProviderStub extends Illuminate\Support\Se protected $defer = true; public function register() { - $this->app->bindShared('foo', function() { + $this->app->singleton('foo', function() { return new StdClass; }); } @@ -247,7 +247,7 @@ class ApplicationMultiProviderStub extends Illuminate\Support\ServiceProvider { protected $defer = true; public function register() { - $this->app->bindShared('foo', function() { return 'foo'; }); - $this->app->bindShared('bar', function($app) { return $app['foo'].'bar'; }); + $this->app->singleton('foo', function() { return 'foo'; }); + $this->app->singleton('bar', function($app) { return $app['foo'].'bar'; }); } } diff --git a/tests/Foundation/FoundationArtisanTest.php b/tests/Foundation/FoundationArtisanTest.php deleted file mode 100755 index 573e377b5..000000000 --- a/tests/Foundation/FoundationArtisanTest.php +++ /dev/null @@ -1,42 +0,0 @@ -getMock( - Artisan::class, - ['getArtisan'], - [$app = new Illuminate\Foundation\Application] - ); - $artisan->expects($this->once())->method('getArtisan')->willReturn( - $console = m::mock('Illuminate\Console\Application[find]') - ); - $console->shouldReceive('find')->once()->with('foo')->andReturn($command = m::mock(\Symfony\Component\Console\Command\Command::class)); - $command->shouldReceive('run')->once()->with(m::type(ArrayInput::class), m::type( - NullOutput::class - ))->andReturnUsing(function($input, $output) use (&$captured) - { - $captured = $input; - - return 0; - }); - - $artisan->call('foo', ['--bar' => 'baz']); - $this->assertEquals('baz', $captured->getParameterOption('--bar')); - } - -} diff --git a/tests/Foundation/FoundationAssetPublishCommandTest.php b/tests/Foundation/FoundationAssetPublishCommandTest.php index 54ed6b32f..269785926 100755 --- a/tests/Foundation/FoundationAssetPublishCommandTest.php +++ b/tests/Foundation/FoundationAssetPublishCommandTest.php @@ -19,6 +19,7 @@ public function testCommandCallsPublisherWithProperPackageName() $pub = m::mock(AssetPublisher::class) ); $pub->shouldReceive('publishPackage')->once()->with('foo'); + $command->setLaravel(tap(new Illuminate\Foundation\Application, fn($a) => $a->instance('env', 'testing'))); $command->run( new Symfony\Component\Console\Input\ArrayInput(['package' => 'foo']), new Symfony\Component\Console\Output\NullOutput diff --git a/tests/Foundation/FoundationConfigPublishCommandTest.php b/tests/Foundation/FoundationConfigPublishCommandTest.php index 5a4f022f6..2d6e75158 100755 --- a/tests/Foundation/FoundationConfigPublishCommandTest.php +++ b/tests/Foundation/FoundationConfigPublishCommandTest.php @@ -20,6 +20,7 @@ public function testCommandCallsPublisherWithProperPackageName() ); $pub->shouldReceive('alreadyPublished')->andReturn(false); $pub->shouldReceive('publishPackage')->once()->with('foo'); + $command->setLaravel(tap(new Illuminate\Foundation\Application, fn($a) => $a->instance('env', 'testing'))); $command->run(new Symfony\Component\Console\Input\ArrayInput(['package' => 'foo']), new Symfony\Component\Console\Output\NullOutput); } diff --git a/tests/Foundation/FoundationViewPublishCommandTest.php b/tests/Foundation/FoundationViewPublishCommandTest.php index 80686136e..7c5ec8339 100755 --- a/tests/Foundation/FoundationViewPublishCommandTest.php +++ b/tests/Foundation/FoundationViewPublishCommandTest.php @@ -19,6 +19,7 @@ public function testCommandCallsPublisherWithProperPackageName() $pub = m::mock(ViewPublisher::class) ); $pub->shouldReceive('publishPackage')->once()->with('foo'); + $command->setLaravel(tap(new Illuminate\Foundation\Application, fn($a) => $a->instance('env', 'testing'))); $command->run( new Symfony\Component\Console\Input\ArrayInput(['package' => 'foo']), new Symfony\Component\Console\Output\NullOutput diff --git a/tests/Http/HttpJsonResponseTest.php b/tests/Http/HttpJsonResponseTest.php deleted file mode 100644 index 6f79a83d0..000000000 --- a/tests/Http/HttpJsonResponseTest.php +++ /dev/null @@ -1,34 +0,0 @@ - 'bar']); - $data = $response->getData(); - $this->assertInstanceOf('StdClass', $data); - $this->assertEquals('bar', $data->foo); - } - - - public function testSetAndRetrieveOptions() - { - $response = new Illuminate\Http\JsonResponse(['foo' => 'bar']); - $response->setJsonOptions(JSON_PRETTY_PRINT); - $this->assertSame(JSON_PRETTY_PRINT, $response->getJsonOptions()); - } - - - public function testSetAndRetrieveStatusCode() - { - $response = new Illuminate\Http\JsonResponse(['foo' => 'bar'], 404); - $this->assertSame(404, $response->getStatusCode()); - - $response = new Illuminate\Http\JsonResponse(['foo' => 'bar']); - $response->setStatusCode(404); - $this->assertSame(404, $response->getStatusCode()); - } - -} diff --git a/tests/Http/HttpRedirectResponseTest.php b/tests/Http/HttpRedirectResponseTest.php deleted file mode 100755 index 5c2fde8e4..000000000 --- a/tests/Http/HttpRedirectResponseTest.php +++ /dev/null @@ -1,142 +0,0 @@ -assertNull($response->headers->get('foo')); - $response->header('foo', 'bar'); - $this->assertEquals('bar', $response->headers->get('foo')); - $response->header('foo', 'baz', false); - $this->assertEquals('bar', $response->headers->get('foo')); - $response->header('foo', 'baz'); - $this->assertEquals('baz', $response->headers->get('foo')); - } - - - public function testWithOnRedirect() -{ - $response = new RedirectResponse('foo.bar'); - $response->setRequest(Request::create('/', 'GET', ['name' => 'Taylor', 'age' => 26])); - $response->setSession($session = m::mock(Store::class)); - $session->shouldReceive('flash')->twice(); - $response->with(['name', 'age']); - } - - - public function testWithCookieOnRedirect() - { - $response = new RedirectResponse('foo.bar'); - $this->assertCount(0, $response->headers->getCookies()); - $this->assertEquals($response, $response->withCookie(new Cookie('foo', 'bar'))); - $cookies = $response->headers->getCookies(); - $this->assertCount(1, $cookies); - $this->assertEquals('foo', $cookies[0]->getName()); - $this->assertEquals('bar', $cookies[0]->getValue()); - } - - - public function testInputOnRedirect() - { - $response = new RedirectResponse('foo.bar'); - $response->setRequest(Request::create('/', 'GET', ['name' => 'Taylor', 'age' => 26])); - $response->setSession($session = m::mock(Store::class)); - $session->shouldReceive('flashInput')->once()->with(['name' => 'Taylor', 'age' => 26]); - $response->withInput(); - } - - - public function testOnlyInputOnRedirect() - { - $response = new RedirectResponse('foo.bar'); - $response->setRequest(Request::create('/', 'GET', ['name' => 'Taylor', 'age' => 26])); - $response->setSession($session = m::mock(Store::class)); - $session->shouldReceive('flashInput')->once()->with(['name' => 'Taylor']); - $response->onlyInput('name'); - } - - - public function testExceptInputOnRedirect() - { - $response = new RedirectResponse('foo.bar'); - $response->setRequest(Request::create('/', 'GET', ['name' => 'Taylor', 'age' => 26])); - $response->setSession($session = m::mock(Store::class)); - $session->shouldReceive('flashInput')->once()->with(['name' => 'Taylor']); - $response->exceptInput('age'); - } - - - public function testFlashingErrorsOnRedirect() - { - $response = new RedirectResponse('foo.bar'); - $response->setRequest(Request::create('/', 'GET', ['name' => 'Taylor', 'age' => 26])); - $response->setSession($session = m::mock(Store::class)); - $session->shouldReceive('get')->with('errors', m::type(ViewErrorBag::class))->andReturn(new Illuminate\Support\ViewErrorBag); - $session->shouldReceive('flash')->once()->with('errors', m::type(ViewErrorBag::class)); - $provider = m::mock(MessageProviderInterface::class); - $provider->shouldReceive('getMessageBag')->once()->andReturn(new Illuminate\Support\MessageBag); - $response->withErrors($provider); - } - - - public function testSettersGettersOnRequest() - { - $response = new RedirectResponse('foo.bar'); - $this->assertNull($response->getRequest()); - $this->assertNull($response->getSession()); - - $request = Request::create('/', 'GET'); - $session = m::mock(Store::class); - $response->setRequest($request); - $response->setSession($session); - $this->assertSame($request, $response->getRequest()); - $this->assertSame($session, $response->getSession()); - } - - - public function testRedirectWithErrorsArrayConvertsToMessageBag() - { - $response = new RedirectResponse('foo.bar'); - $response->setRequest(Request::create('/', 'GET', ['name' => 'Taylor', 'age' => 26])); - $response->setSession($session = m::mock(Store::class)); - $session->shouldReceive('get')->with('errors', m::type(ViewErrorBag::class))->andReturn(new Illuminate\Support\ViewErrorBag); - $session->shouldReceive('flash')->once()->with('errors', m::type(ViewErrorBag::class)); - $provider = ['foo' => 'bar']; - $response->withErrors($provider); - } - - - public function testMagicCall() - { - $response = new RedirectResponse('foo.bar'); - $response->setRequest(Request::create('/', 'GET', ['name' => 'Taylor', 'age' => 26])); - $response->setSession($session = m::mock(Store::class)); - $session->shouldReceive('flash')->once()->with('foo', 'bar'); - $response->withFoo('bar'); - } - - - public function testMagicCallException() - { - $this->expectException('BadMethodCallException'); - $response = new RedirectResponse('foo.bar'); - $response->doesNotExist('bar'); - } - -} diff --git a/tests/Http/HttpRequestTest.php b/tests/Http/HttpRequestTest.php deleted file mode 100755 index 656b83737..000000000 --- a/tests/Http/HttpRequestTest.php +++ /dev/null @@ -1,428 +0,0 @@ -assertSame($request, $request->instance()); - } - - - public function testRootMethod() - { - $request = Request::create('http://example.com/foo/bar/script.php?test'); - $this->assertEquals('http://example.com', $request->root()); - } - - - public function testPathMethod() - { - $request = Request::create('', 'GET'); - $this->assertEquals('/', $request->path()); - - $request = Request::create('/foo/bar', 'GET'); - $this->assertEquals('foo/bar', $request->path()); - } - - - public function testDecodedPathMethod() - { - $request = Request::create('/foo%20bar'); - $this->assertEquals('foo bar', $request->decodedPath()); - } - - - /** - * @dataProvider segmentProvider - */ - public function testSegmentMethod($path, $segment, $expected) - { - $request = Request::create($path, 'GET'); - $this->assertEquals($expected, $request->segment($segment, 'default')); - } - - - public function segmentProvider() - { - return [ - ['', 1, 'default'], - ['foo/bar//baz', '1', 'foo'], - ['foo/bar//baz', '2', 'bar'], - ['foo/bar//baz', '3', 'baz'], - ]; - } - - /** - * @dataProvider segmentsProvider - */ - public function testSegmentsMethod($path, $expected) - { - $request = Request::create($path, 'GET'); - $this->assertEquals($expected, $request->segments()); - - $request = Request::create('foo/bar', 'GET'); - $this->assertEquals(['foo', 'bar'], $request->segments()); - } - - - public function segmentsProvider() - { - return [ - ['', []], - ['foo/bar', ['foo', 'bar']], - ['foo/bar//baz', ['foo', 'bar', 'baz']], - ['foo/0/bar', ['foo', '0', 'bar']], - ]; - } - - - public function testUrlMethod() - { - $request = Request::create('http://foo.com/foo/bar?name=taylor', 'GET'); - $this->assertEquals('http://foo.com/foo/bar', $request->url()); - - $request = Request::create('http://foo.com/foo/bar/?', 'GET'); - $this->assertEquals('http://foo.com/foo/bar', $request->url()); - } - - - public function testFullUrlMethod() - { - $request = Request::create('http://foo.com/foo/bar?name=taylor', 'GET'); - $this->assertEquals('http://foo.com/foo/bar?name=taylor', $request->fullUrl()); - - $request = Request::create('https://foo.com', 'GET'); - $this->assertEquals('https://foo.com', $request->fullUrl()); - } - - - public function testIsMethod() - { - $request = Request::create('/foo/bar', 'GET'); - - $this->assertTrue($request->is('foo*')); - $this->assertFalse($request->is('bar*')); - $this->assertTrue($request->is('*bar*')); - $this->assertTrue($request->is('bar*', 'foo*', 'baz')); - - $request = Request::create('/', 'GET'); - - $this->assertTrue($request->is('/')); - } - - - public function testAjaxMethod() - { - $request = Request::create('/', 'GET'); - $this->assertFalse($request->ajax()); - $request = Request::create('/', 'GET', [], [], [], ['HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest'], '{}'); - $this->assertTrue($request->ajax()); - } - - - public function testSecureMethod() - { - $request = Request::create('http://example.com', 'GET'); - $this->assertFalse($request->secure()); - $request = Request::create('https://example.com', 'GET'); - $this->assertTrue($request->secure()); - } - - - public function testHasMethod() - { - $request = Request::create('/', 'GET', ['name' => 'Taylor']); - $this->assertTrue($request->has('name')); - $this->assertFalse($request->has('foo')); - $this->assertFalse($request->has('name', 'email')); - - $request = Request::create('/', 'GET', ['name' => 'Taylor', 'email' => 'foo']); - $this->assertTrue($request->has('name')); - $this->assertTrue($request->has('name', 'email')); - - //test arrays within query string - $request = Request::create('/', 'GET', ['foo' => ['bar', 'baz']]); - $this->assertTrue($request->has('foo')); - } - - - public function testInputMethod() - { - $request = Request::create('/', 'GET', ['name' => 'Taylor']); - $this->assertEquals('Taylor', $request->input('name')); - $this->assertEquals('Bob', $request->input('foo', 'Bob')); - } - - - public function testOnlyMethod() - { - $request = Request::create('/', 'GET', ['name' => 'Taylor', 'age' => 25]); - $this->assertEquals(['age' => 25], $request->only('age')); - $this->assertEquals(['name' => 'Taylor', 'age' => 25], $request->only('name', 'age')); - - $request = Request::create('/', 'GET', ['developer' => ['name' => 'Taylor', 'age' => 25]]); - $this->assertEquals(['developer' => ['age' => 25]], $request->only('developer.age')); - $this->assertEquals(['developer' => ['name' => 'Taylor'], 'test' => null], $request->only('developer.name', 'test')); - } - - - public function testExceptMethod() - { - $request = Request::create('/', 'GET', ['name' => 'Taylor', 'age' => 25]); - $this->assertEquals(['name' => 'Taylor'], $request->except('age')); - $this->assertEquals([], $request->except('age', 'name')); - } - - - public function testQueryMethod() - { - $request = Request::create('/', 'GET', ['name' => 'Taylor']); - $this->assertEquals('Taylor', $request->query('name')); - $this->assertEquals('Bob', $request->query('foo', 'Bob')); - $all = $request->query(null); - $this->assertEquals('Taylor', $all['name']); - - $request = Request::create('/', 'GET', ['hello' => 'world', 'user' => ['Taylor', 'Mohamed Said']]); - $this->assertSame(['Taylor', 'Mohamed Said'], $request->query('user')); - $this->assertSame(['hello' => 'world', 'user' => ['Taylor', 'Mohamed Said']], $request->query->all()); - - $request = Request::create('/?hello=world&user[]=Taylor&user[]=Mohamed%20Said', 'GET', []); - $this->assertSame(['Taylor', 'Mohamed Said'], $request->query('user')); - $this->assertSame(['hello' => 'world', 'user' => ['Taylor', 'Mohamed Said']], $request->query->all()); - } - - - public function testCookieMethod() - { - $request = Request::create('/', 'GET', [], ['name' => 'Taylor']); - $this->assertEquals('Taylor', $request->cookie('name')); - $this->assertEquals('Bob', $request->cookie('foo', 'Bob')); - $all = $request->cookie(null); - $this->assertEquals('Taylor', $all['name']); - } - - - public function testHasCookieMethod() - { - $request = Request::create('/', 'GET', [], ['foo' => 'bar']); - $this->assertTrue($request->hasCookie('foo')); - $this->assertFalse($request->hasCookie('qu')); - } - - - public function testFileMethod() - { - $files = [ - 'foo' => [ - 'size' => 500, - 'name' => 'foo.jpg', - 'tmp_name' => __FILE__, - 'type' => 'blah', - 'error' => null, - ], - ]; - $request = Request::create('/', 'GET', [], [], $files); - $this->assertInstanceOf(UploadedFile::class, $request->file('foo')); - } - - - public function testHasFileMethod() - { - $request = Request::create('/', 'GET', [], [], []); - $this->assertFalse($request->hasFile('foo')); - - $files = [ - 'foo' => [ - 'size' => 500, - 'name' => 'foo.jpg', - 'tmp_name' => __FILE__, - 'type' => 'blah', - 'error' => null, - ], - ]; - $request = Request::create('/', 'GET', [], [], $files); - $this->assertTrue($request->hasFile('foo')); - } - - - public function testServerMethod() - { - $request = Request::create('/', 'GET', [], [], [], ['foo' => 'bar']); - $this->assertEquals('bar', $request->server('foo')); - $this->assertEquals('bar', $request->server('foo.doesnt.exist', 'bar')); - $all = $request->server(null); - $this->assertEquals('bar', $all['foo']); - } - - - public function testMergeMethod() - { - $request = Request::create('/', 'GET', ['name' => 'Taylor']); - $merge = ['buddy' => 'Dayle']; - $request->merge($merge); - $this->assertEquals('Taylor', $request->input('name')); - $this->assertEquals('Dayle', $request->input('buddy')); - } - - - public function testReplaceMethod() - { - $request = Request::create('/', 'GET', ['name' => 'Taylor']); - $replace = ['buddy' => 'Dayle']; - $request->replace($replace); - $this->assertNull($request->input('name')); - $this->assertEquals('Dayle', $request->input('buddy')); - } - - - public function testHeaderMethod() - { - $request = Request::create('/', 'GET', [], [], [], ['HTTP_DO_THIS' => 'foo']); - $this->assertEquals('foo', $request->header('do-this')); - $all = $request->header(null); - $this->assertEquals('foo', $all['do-this'][0]); - } - - - public function testJSONMethod() - { - $payload = ['name' => 'taylor']; - $request = Request::create('/', 'GET', [], [], [], ['CONTENT_TYPE' => 'application/json'], json_encode($payload)); - $this->assertEquals('taylor', $request->json('name')); - $this->assertEquals('taylor', $request->input('name')); - $data = $request->json()->all(); - $this->assertEquals($payload, $data); - } - - - public function testJSONEmulatingPHPBuiltInServer() - { - $payload = ['name' => 'taylor']; - $content = json_encode($payload); - // The built in PHP 5.4 webserver incorrectly provides HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH, - // rather than CONTENT_TYPE and CONTENT_LENGTH - $request = Request::create('/', 'GET', [], [], [], ['HTTP_CONTENT_TYPE' => 'application/json', 'HTTP_CONTENT_LENGTH' => strlen($content)], $content); - $this->assertTrue($request->isJson()); - $data = $request->json()->all(); - $this->assertEquals($payload, $data); - - $data = $request->all(); - $this->assertEquals($payload, $data); - } - - - public function testAllInputReturnsInputAndFiles() - { - $file = $this->getMock(UploadedFile::class, null, [__FILE__, 'photo.jpg']); - $request = Request::create('/?boom=breeze', 'GET', ['foo' => 'bar'], [], ['baz' => $file]); - $this->assertEquals(['foo' => 'bar', 'baz' => $file, 'boom' => 'breeze'], $request->all()); - } - - - public function testAllInputReturnsNestedInputAndFiles() - { - $file = $this->getMock(UploadedFile::class, null, [__FILE__, 'photo.jpg']); - $request = Request::create('/?boom=breeze', 'GET', ['foo' => ['bar' => 'baz']], [], ['foo' => ['photo' => $file]] - ); - $this->assertEquals(['foo' => ['bar' => 'baz', 'photo' => $file], 'boom' => 'breeze'], $request->all()); - } - - - public function testAllInputReturnsInputAfterReplace() - { - $request = Request::create('/?boom=breeze', 'GET', ['foo' => ['bar' => 'baz']]); - $request->replace(['foo' => ['bar' => 'baz'], 'boom' => 'breeze']); - $this->assertEquals(['foo' => ['bar' => 'baz'], 'boom' => 'breeze'], $request->all()); - } - - - public function testAllInputWithNumericKeysReturnsInputAfterReplace() - { - $request1 = Request::create('/', 'POST', [0 => 'A', 1 => 'B', 2 => 'C']); - $request1->replace([0 => 'A', 1 => 'B', 2 => 'C']); - $this->assertEquals([0 => 'A', 1 => 'B', 2 => 'C'], $request1->all()); - - $request2 = Request::create('/', 'POST', [1 => 'A', 2 => 'B', 3 => 'C']); - $request2->replace([1 => 'A', 2 => 'B', 3 => 'C']); - $this->assertEquals([1 => 'A', 2 => 'B', 3 => 'C'], $request2->all()); - } - - - public function testOldMethodCallsSession() - { - $request = Request::create('/', 'GET'); - $session = m::mock(Store::class); - $session->shouldReceive('getOldInput')->once()->with('foo', 'bar')->andReturn('boom'); - $request->setLaravelSession($session); - $this->assertEquals('boom', $request->old('foo', 'bar')); - } - - - public function testFlushMethodCallsSession() - { - $request = Request::create('/', 'GET'); - $session = m::mock(Store::class); - $session->shouldReceive('flashInput')->once(); - $request->setLaravelSession($session); - $request->flush(); - } - - - public function testFormatReturnsAcceptableFormat() - { - $request = Request::create('/', 'GET', [], [], [], ['HTTP_ACCEPT' => 'application/json']); - $this->assertEquals('json', $request->format()); - $this->assertTrue($request->wantsJson()); - - $request = Request::create('/', 'GET', [], [], [], ['HTTP_ACCEPT' => 'application/atom+xml']); - $this->assertEquals('atom', $request->format()); - $this->assertFalse($request->wantsJson()); - - $request = Request::create('/', 'GET', [], [], [], ['HTTP_ACCEPT' => 'is/not/known']); - $this->assertEquals('html', $request->format()); - $this->assertEquals('foo', $request->format('foo')); - } - - - public function testSessionMethod() - { - $this->expectException('RuntimeException'); - $request = Request::create('/', 'GET'); - $request->session(); - } - - - public function testCreateFromBase() - { - $body = [ - 'foo' => 'bar', - 'baz' => ['qux'], - ]; - - $server = [ - 'CONTENT_TYPE' => 'application/json', - ]; - - $base = SymfonyRequest::create('/', 'GET', [], [], [], $server, json_encode($body)); - - $request = Request::createFromBase($base); - - $this->assertEquals($request->request->all(), $body); - } - -} diff --git a/tests/Http/HttpResponseTest.php b/tests/Http/HttpResponseTest.php deleted file mode 100755 index d245e3118..000000000 --- a/tests/Http/HttpResponseTest.php +++ /dev/null @@ -1,143 +0,0 @@ -assertSame('{"foo":"bar"}', $response->getContent()); - $this->assertSame('application/json', $response->headers->get('Content-Type')); - - $response = new Response(new JsonableStub); - $this->assertSame('foo', $response->getContent()); - $this->assertSame('application/json', $response->headers->get('Content-Type')); - - $response = new Response(new ArrayableAndJsonableStub); - $this->assertSame('{"foo":"bar"}', $response->getContent()); - $this->assertSame('application/json', $response->headers->get('Content-Type')); - - $response = new Response; - $response->setContent(['foo' => 'bar']); - $this->assertSame('{"foo":"bar"}', $response->getContent()); - $this->assertSame('application/json', $response->headers->get('Content-Type')); - - $response = new Response(new JsonSerializableStub); - $this->assertSame('{"foo":"bar"}', $response->getContent()); - $this->assertSame('application/json', $response->headers->get('Content-Type')); - - $response = new Response(new ArrayableStub); - $this->assertSame('{"foo":"bar"}', $response->getContent()); - $this->assertSame('application/json', $response->headers->get('Content-Type')); - - $response->setContent('{"foo": "bar"}'); - $this->assertSame('{"foo": "bar"}', $response->getContent()); - $this->assertSame('application/json', $response->headers->get('Content-Type')); - } - - - public function testRenderablesAreRendered() - { - $mock = m::mock(Renderable::class); - $mock->shouldReceive('render')->once()->andReturn('foo'); - $response = new Response($mock); - $this->assertEquals('foo', $response->getContent()); - } - - - public function testHeader() - { - $response = new Response(); - $this->assertNull($response->headers->get('foo')); - $response->header('foo', 'bar'); - $this->assertEquals('bar', $response->headers->get('foo')); - $response->header('foo', 'baz', false); - $this->assertEquals('bar', $response->headers->get('foo')); - $response->header('foo', 'baz'); - $this->assertEquals('baz', $response->headers->get('foo')); - } - - - public function testWithCookie() - { - $response = new Response(); - $this->assertCount(0, $response->headers->getCookies()); - $this->assertEquals($response, $response->withCookie(new Cookie('foo', 'bar'))); - $cookies = $response->headers->getCookies(); - $this->assertCount(1, $cookies); - $this->assertEquals('foo', $cookies[0]->getName()); - $this->assertEquals('bar', $cookies[0]->getValue()); - } - - - public function testGetOriginalContent() - { - $arr = ['foo' => 'bar']; - $response = new Response(); - $response->setContent($arr); - $this->assertSame($arr, $response->getOriginalContent()); - } - - - public function testSetAndRetrieveStatusCode() - { - $response = new Response('foo', 404); - $this->assertSame(404, $response->getStatusCode()); - - $response = new Response('foo'); - $response->setStatusCode(404); - $this->assertSame(404, $response->getStatusCode()); - } - -} - -class ArrayableStub implements ArrayableInterface -{ - public function toArray() - { - return ['foo' => 'bar']; - } -} - -class ArrayableAndJsonableStub implements ArrayableInterface, JsonableInterface -{ - public function toJson($options = 0) - { - return '{"foo":"bar"}'; - } - - public function toArray() - { - return []; - } -} - -class JsonableStub implements JsonableInterface -{ - public function toJson($options = 0) - { - return 'foo'; - } -} - -class JsonSerializableStub implements JsonSerializable -{ - public function jsonSerialize(): array - { - return ['foo' => 'bar']; - } -} \ No newline at end of file diff --git a/tests/Mail/MailMailerTest.php b/tests/Mail/MailMailerTest.php index 7b6fea15a..b06d1e524 100755 --- a/tests/Mail/MailMailerTest.php +++ b/tests/Mail/MailMailerTest.php @@ -213,7 +213,7 @@ public function mail(Message $message): void $this->calledTimes++; } }; - $container['FooMailer'] = $container->share(fn() => $fooMailer); + $container->singleton('FooMailer', fn() => $fooMailer); $mailer->send('foo', ['data'], 'FooMailer'); diff --git a/tests/Pagination/PaginationBootstrapPresenterTest.php b/tests/Pagination/PaginationBootstrapPresenterTest.php deleted file mode 100755 index e2b575ffc..000000000 --- a/tests/Pagination/PaginationBootstrapPresenterTest.php +++ /dev/null @@ -1,174 +0,0 @@ -getPresenter(); - } - - - public function testSimpleRangeIsReturnedWhenCantBuildSlier() - { - $presenter = $this->getMock(BootstrapPresenter::class, ['getPageRange', 'getPrevious', 'getNext'], [$paginator = $this->getPaginator()] - ); - $presenter->expects($this->once())->method('getPageRange')->with($this->equalTo(1), $this->equalTo(2))->willReturn( - 'bar' - ); - $presenter->expects($this->once())->method('getPrevious')->willReturn('foo'); - $presenter->expects($this->once())->method('getNext')->willReturn('baz'); - - $this->assertEquals('foobarbaz', $presenter->render()); - } - - - public function testGetPageRange() - { - $presenter = $this->getPresenter(); - $presenter->setCurrentPage(1); - $content = $presenter->getPageRange(1, 2); - - $this->assertEquals('
  • 1
  • 2
  • ', $content); - } - - - public function testBeginningSliderIsCreatedWhenCloseToStart() - { - $presenter = $this->getMock(BootstrapPresenter::class, ['getPageRange', 'getPrevious', 'getNext', 'getStart', 'getFinish'], [$paginator = $this->getPaginator()] - ); - $presenter->setLastPage(14); - $presenter->expects($this->once())->method('getFinish')->willReturn('finish'); - $presenter->expects($this->once())->method('getPrevious')->willReturn('previous'); - $presenter->expects($this->once())->method('getNext')->willReturn('next'); - $presenter->expects($this->once())->method('getPageRange')->with($this->equalTo(1), $this->equalTo(8))->willReturn( - 'range' - ); - - $this->assertEquals('previousrangefinishnext', $presenter->render()); - } - - - public function testEndingSliderIsCreatedWhenCloseToStart() - { - $presenter = $this->getMock(BootstrapPresenter::class, ['getPageRange', 'getPrevious', 'getNext', 'getStart', 'getFinish'], [$paginator = $this->getPaginator()] - ); - $presenter->setLastPage(14); - $presenter->setCurrentPage(13); - $presenter->expects($this->once())->method('getStart')->willReturn('start'); - $presenter->expects($this->once())->method('getPrevious')->willReturn('previous'); - $presenter->expects($this->once())->method('getNext')->willReturn('next'); - $presenter->expects($this->once())->method('getPageRange')->with($this->equalTo(6), $this->equalTo(14))->willReturn( - 'range' - ); - - $this->assertEquals('previousstartrangenext', $presenter->render()); - } - - - public function testSliderIsCreatedWhenCloseToStart() - { - $presenter = $this->getMock(BootstrapPresenter::class, ['getPageRange', 'getPrevious', 'getNext', 'getStart', 'getFinish'], [$paginator = $this->getPaginator()] - ); - $presenter->setLastPage(30); - $presenter->setCurrentPage(15); - $presenter->expects($this->once())->method('getStart')->willReturn('start'); - $presenter->expects($this->once())->method('getFinish')->willReturn('finish'); - $presenter->expects($this->once())->method('getPrevious')->willReturn('previous'); - $presenter->expects($this->once())->method('getNext')->willReturn('next'); - $presenter->expects($this->once())->method('getPageRange')->with($this->equalTo(12), $this->equalTo(18))->willReturn( - 'range' - ); - - $this->assertEquals('previousstartrangefinishnext', $presenter->render()); - } - - - public function testPreviousLinkCanBeRendered() - { - $output = $this->getPresenter()->getPrevious(); - - $this->assertEquals('
  • «
  • ', $output); - - $presenter = $this->getPresenter(); - $presenter->setCurrentPage(2); - $output = $presenter->getPrevious(); - - $this->assertEquals('
  • ', $output); - } - - - public function testNextLinkCanBeRendered() - { - $presenter = $this->getPresenter(); - $presenter->setCurrentPage(2); - $output = $presenter->getNext(); - - $this->assertEquals('
  • »
  • ', $output); - - $presenter = $this->getPresenter(); - $presenter->setCurrentPage(1); - $output = $presenter->getNext(); - - $this->assertEquals('
  • ', $output); - } - - - public function testGetStart() - { - $presenter = $this->getPresenter(); - $output = $presenter->getStart(); - - $this->assertEquals('
  • 1
  • 2
  • ...
  • ', $output); - } - - - public function testGetFinish() - { - $presenter = $this->getPresenter(); - $output = $presenter->getFinish(); - - $this->assertEquals('
  • ...
  • 1
  • 2
  • ', $output); - } - - - public function testGetAdjacentRange() - { - $presenter = $this->getMock(BootstrapPresenter::class, ['getPageRange'], [$paginator = $this->getPaginator()]); - $presenter->expects($this->once())->method('getPageRange')->with($this->equalTo(1), $this->equalTo(7))->willReturn( - 'foo' - ); - $presenter->setCurrentPage(4); - - $this->assertEquals('foo', $presenter->getAdjacentRange()); - } - - - - protected function getPresenter() - { - return new BootstrapPresenter($this->getPaginator()); - } - - - protected function getPaginator() - { - $paginator = m::mock(Paginator::class); - $paginator->shouldReceive('lastPage')->once()->andReturn(2); - $paginator->shouldReceive('currentPage')->once()->andReturn(1); - $paginator->shouldReceive('getUrl')->andReturnUsing(function($page) { return 'http://foo.com?page='.$page; }); - return $paginator; - } - -} diff --git a/tests/Pagination/PaginationCustomPresenterTest.php b/tests/Pagination/PaginationCustomPresenterTest.php deleted file mode 100644 index dddb33b52..000000000 --- a/tests/Pagination/PaginationCustomPresenterTest.php +++ /dev/null @@ -1,52 +0,0 @@ -shouldReceive('getPageLinkWrapper') - ->once() - ->andReturnUsing(function($url, $page) { - return '' . $page . ''; - }); - - $this->assertEquals('1', $customPresenter->getPageLinkWrapper('http://laravel.com?page=1', '1', null)); - } - - - public function testGetDisabledTextWrapper() - { - $customPresenter = m::mock(Presenter::class); - $customPresenter->shouldReceive('getDisabledTextWrapper') - ->once() - ->andReturnUsing(function($text) { - return '
  • ' . $text . '
  • '; - }); - $this->assertEquals('
  • foo
  • ', $customPresenter->getDisabledTextWrapper('foo')); - } - - - public function testGetActiveTextWrapper() - { - $customPresenter = m::mock(Presenter::class); - $customPresenter->shouldReceive('getActiveTextWrapper') - ->once() - ->andReturnUsing(function($text) { - return '
  • ' . $text . '
  • '; - }); - $this->assertEquals('
  • bazzer
  • ', $customPresenter->getActiveTextWrapper('bazzer')); - } - -} diff --git a/tests/Pagination/PaginationFactoryTest.php b/tests/Pagination/PaginationFactoryTest.php deleted file mode 100755 index d3cce9830..000000000 --- a/tests/Pagination/PaginationFactoryTest.php +++ /dev/null @@ -1,111 +0,0 @@ -getFactory(); - } - - - public function testPaginatorCanBeCreated() - { - $env = $this->getFactory(); - $request = Illuminate\Http\Request::create('http://foo.com', 'GET'); - $env->setRequest($request); - - $this->assertInstanceOf(Paginator::class, $env->make(['foo', 'bar'], 2, 2)); - } - - - public function testPaginationViewCanBeCreated() - { - $env = $this->getFactory(); - $paginator = m::mock(Paginator::class); - $env->getViewFactory()->shouldReceive('make')->once()->with('pagination::slider', ['environment' => $env, 'paginator' => $paginator] - )->andReturn('foo'); - - $this->assertEquals('foo', $env->getPaginationView($paginator)); - } - - - public function testCurrentPageCanBeRetrieved() - { - $env = $this->getFactory(); - $request = Illuminate\Http\Request::create('http://foo.com?page=2', 'GET'); - $env->setRequest($request); - - $this->assertEquals(2, $env->getCurrentPage()); - - $env = $this->getFactory(); - $request = Illuminate\Http\Request::create('http://foo.com?page=-1', 'GET'); - $env->setRequest($request); - - $this->assertEquals(1, $env->getCurrentPage()); - } - - - public function testSettingCurrentUrlOverrulesRequest() - { - $env = $this->getFactory(); - $request = Illuminate\Http\Request::create('http://foo.com?page=2', 'GET'); - $env->setRequest($request); - $env->setCurrentPage(3); - - $this->assertEquals(3, $env->getCurrentPage()); - } - - - public function testCurrentUrlCanBeRetrieved() - { - $env = $this->getFactory(); - $request = Illuminate\Http\Request::create('http://foo.com/bar?page=2', 'GET'); - $env->setRequest($request); - - $this->assertEquals('http://foo.com/bar', $env->getCurrentUrl()); - - $env = $this->getFactory(); - $request = Illuminate\Http\Request::create('http://foo.com?page=2', 'GET'); - $env->setRequest($request); - - $this->assertEquals('http://foo.com', $env->getCurrentUrl()); - } - - - public function testOverridingPageParam() - { - $env = $this->getFactory(); - $this->assertEquals('page', $env->getPageName()); - $env->setPageName('foo'); - $this->assertEquals('foo', $env->getPageName()); - } - - - protected function getFactory() - { - $request = m::mock(Request::class); - $view = m::mock(\Illuminate\View\Factory::class); - $trans = m::mock(TranslatorInterface::class); - $view->shouldReceive('addNamespace')->once()->with( - 'pagination', - realpath(__DIR__ . '/../../src/Illuminate/Pagination') . '/views' - ); - - return new Factory($request, $view, $trans, 'page'); - } - -} diff --git a/tests/Pagination/PaginationPaginatorTest.php b/tests/Pagination/PaginationPaginatorTest.php deleted file mode 100755 index c5a4a2fa9..000000000 --- a/tests/Pagination/PaginationPaginatorTest.php +++ /dev/null @@ -1,227 +0,0 @@ -shouldReceive('getCurrentPage')->once()->andReturn(1); - $p->setupPaginationContext(); - - $this->assertEquals(2, $p->lastPage()); - $this->assertEquals(1, $p->currentPage()); - } - - - public function testPaginationContextIsSetupCorrectlyWithEmptyItems() - { - $p = new Paginator($factory = m::mock(Factory::class), [], 0, 2); - $factory->shouldReceive('getCurrentPage')->once()->andReturn(1); - $p->setupPaginationContext(); - - $this->assertEquals(1, $p->lastPage()); - $this->assertEquals(1, $p->currentPage()); - } - - - public function testSimplePagination() - { - $p = new Paginator($factory = m::mock(Factory::class), ['foo', 'bar', 'baz'], 2); - $factory->shouldReceive('getCurrentPage')->once()->andReturn(1); - $p->setupPaginationContext(); - - $this->assertEquals(2, $p->lastPage()); - $this->assertEquals(1, $p->currentPage()); - $this->assertEquals(['foo', 'bar'], $p->items()); - } - - - public function testSimplePaginationLastPage() - { - $p = new Paginator($factory = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3); - $factory->shouldReceive('getCurrentPage')->once()->andReturn(1); - $p->setupPaginationContext(); - - $this->assertEquals(1, $p->lastPage()); - $this->assertEquals(1, $p->currentPage()); - $this->assertCount(3, $p->items()); - } - - - public function testPaginationContextIsSetupCorrectlyInCursorMode() - { - $p = new Paginator($factory = m::mock(Factory::class), ['foo', 'bar', 'baz'], 2); - $factory->shouldReceive('getCurrentPage')->once()->andReturn(1); - $p->setupPaginationContext(); - - $this->assertEquals(2, $p->lastPage()); - $this->assertEquals(1, $p->currentPage()); - } - - - public function testPaginationContextSetsUpRangeCorrectly() - { - $p = new Paginator($factory = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3, 2); - $factory->shouldReceive('getCurrentPage')->once()->andReturn(1); - $p->setupPaginationContext(); - - $this->assertEquals(1, $p->firstItem()); - $this->assertEquals(2, $p->lastItem()); - } - - - public function testPaginationContextHandlesHugeCurrentPage() - { - $p = new Paginator($factory = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3, 2); - $factory->shouldReceive('getCurrentPage')->once()->andReturn(15); - $p->setupPaginationContext(); - - $this->assertEquals(2, $p->lastPage()); - $this->assertEquals(2, $p->currentPage()); - } - - - public function testPaginationContextHandlesPageLessThanOne() - { - $p = new Paginator($factory = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3, 2); - $factory->shouldReceive('getCurrentPage')->once()->andReturn(-1); - $p->setupPaginationContext(); - - $this->assertEquals(2, $p->lastPage()); - $this->assertEquals(1, $p->currentPage()); - } - - - public function testPaginationContextHandlesPageLessThanOneAsString() - { - $p = new Paginator($factory = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3, 2); - $factory->shouldReceive('getCurrentPage')->once()->andReturn('-1'); - $p->setupPaginationContext(); - - $this->assertEquals(2, $p->lastPage()); - $this->assertEquals(1, $p->currentPage()); - } - - - public function testPaginationContextHandlesPageInvalidFormat() - { - $p = new Paginator($factory = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3, 2); - $factory->shouldReceive('getCurrentPage')->once()->andReturn('abc'); - $p->setupPaginationContext(); - - $this->assertEquals(2, $p->lastPage()); - $this->assertEquals(1, $p->currentPage()); - } - - - public function testPaginationContextHandlesPageMissing() - { - $p = new Paginator($factory = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3, 2); - $factory->shouldReceive('getCurrentPage')->once()->andReturn(null); - $p->setupPaginationContext(); - - $this->assertEquals(2, $p->lastPage()); - $this->assertEquals(1, $p->currentPage()); - } - - - public function testGetLinksCallsEnvironmentProperly() - { - $p = new Paginator($factory = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3, 2); - $factory->shouldReceive('getPaginationView')->once()->with($p, null)->andReturn('foo'); - - $this->assertEquals('foo', $p->links()); - } - - - public function testGetUrlProperlyFormatsUrl() - { - $p = new Paginator($env = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3, 2); - $env->shouldReceive('getCurrentUrl')->andReturn('http://foo.com'); - $env->shouldReceive('getPageName')->andReturn('page'); - - $this->assertEquals('http://foo.com?page=1', $p->getUrl(1)); - $p->addQuery('foo', 'bar'); - $this->assertEquals('http://foo.com?foo=bar&page=1', $p->getUrl(1)); - } - - - public function testEnvironmentAccess() - { - $p = new Paginator($factory = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3, 2); - $this->assertInstanceOf(Factory::class, $p->getFactory()); - } - - - public function testPaginatorIsCountable() - { - $p = new Paginator($factory = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3, 2); - - $this->assertCount(3, $p); - } - - - public function testPaginatorIsIterable() - { - $p = new Paginator($factory = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3, 2); - - $this->assertInstanceOf('ArrayIterator', $p->getIterator()); - $this->assertEquals(['foo', 'bar', 'baz'], $p->getIterator()->getArrayCopy()); - } - - - public function testGetUrlAddsFragment() - { - $p = new Paginator($env = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3, 2); - $env->shouldReceive('getCurrentUrl')->andReturn('http://foo.com'); - $env->shouldReceive('getPageName')->andReturn('page'); - - $p->fragment("a-fragment"); - - $this->assertEquals('http://foo.com?page=1#a-fragment', $p->getUrl(1)); - $p->addQuery('foo', 'bar'); - $this->assertEquals('http://foo.com?foo=bar&page=1#a-fragment', $p->getUrl(1)); - } - - - public function testGetUrlHasPriorityOverAppends() - { - $p = new Paginator($env = m::mock(Factory::class), ['foo', 'bar', 'baz'], 3, 2); - $env->shouldReceive('getCurrentUrl')->andReturn('http://foo.com'); - $env->shouldReceive('getPageName')->andReturn('page'); - - $p->appends([ - 'sort' => 'asc', - 'page' => 2, - ]); - $this->assertEquals('http://foo.com?sort=asc&page=1', $p->getUrl(1)); - - $p->appends([ - 'sort' => 'desc', - 'page' => '2', - ]); - $this->assertEquals('http://foo.com?sort=desc&page=1', $p->getUrl(1)); - } - - - public function testPaginatorDecoratesCollection() - { - $p = new Paginator(m::mock(Factory::class), ['a', 'b', 'c'], 3, 2); - $last = $p->last(); - - $this->assertEquals('c', $last); - } - -} diff --git a/tests/Routing/RoutingMakeControllerCommandTest.php b/tests/Routing/RoutingMakeControllerCommandTest.php index 6876c79df..8fa9f9b02 100755 --- a/tests/Routing/RoutingMakeControllerCommandTest.php +++ b/tests/Routing/RoutingMakeControllerCommandTest.php @@ -23,6 +23,7 @@ public function testGeneratorIsCalledWithProperOptions() __DIR__, ['only' => [], 'except' => []] ); + $command->setLaravel(tap(new Illuminate\Foundation\Application, fn($a) => $a->instance('env', 'testing'))); $this->runCommand($command, ['name' => 'FooController']); } @@ -34,7 +35,10 @@ public function testGeneratorIsCalledWithProperOptionsForExceptAndOnly() ), __DIR__); $gen->shouldReceive('make')->once()->with('FooController', __DIR__.'/foo/bar', ['only' => ['foo', 'bar'], 'except' => ['baz', 'boom']] ); - $command->setLaravel(['path.base' => __DIR__.'/foo']); + $laravel = new Illuminate\Foundation\Application; + $laravel->instance('path.base', __DIR__.'/foo'); + $laravel->instance('env', 'testing'); + $command->setLaravel($laravel); $this->runCommand($command, ['name' => 'FooController', '--only' => 'foo,bar', '--except' => 'baz,boom', '--path' => 'bar'] ); } diff --git a/tests/Session/SessionMiddlewareTest.php b/tests/Session/SessionMiddlewareTest.php deleted file mode 100644 index 99f742216..000000000 --- a/tests/Session/SessionMiddlewareTest.php +++ /dev/null @@ -1,86 +0,0 @@ -shouldReceive('getSessionConfig')->andReturn([ - 'driver' => 'file', - 'lottery' => [100, 100], - 'path' => '/', - 'domain' => null, - 'lifetime' => 120, - 'expire_on_close' => false, - ]); - - $manager->shouldReceive('driver')->andReturn($driver = m::mock(Store::class)->makePartial()); - $driver->shouldReceive('setRequestOnHandler')->once()->with($request); - $driver->shouldReceive('start')->once(); - $app->shouldReceive('handle')->once()->with($request, Symfony\Component\HttpKernel\HttpKernelInterface::MAIN_REQUEST, true)->andReturn($response); - $driver->shouldReceive('save')->once(); - $driver->shouldReceive('getHandler')->andReturn($handler = m::mock('StdClass')); - $handler->shouldReceive('gc')->once()->with(120 * 60); - $driver->shouldReceive('getName')->andReturn('name'); - $driver->shouldReceive('getId')->andReturn(1); - $driver->shouldReceive('setPreviousUrl')->with('http://www.foo.com/some')->once(); - - $middleResponse = $middle->handle($request); - - $this->assertSame($response, $middleResponse); - $this->assertEquals(1, head($response->headers->getCookies())->getValue()); - } - - - public function testSessionIsNotUsedWhenNoDriver() - { - $request = Symfony\Component\HttpFoundation\Request::create('/', 'GET'); - $response = new Symfony\Component\HttpFoundation\Response; - $middle = new Illuminate\Session\Middleware( - $app = m::mock(HttpKernelInterface::class), - $manager = m::mock(SessionManager::class) - ); - $manager->shouldReceive('getSessionConfig')->andReturn([ - 'driver' => null, - ]); - $app->shouldReceive('handle')->once()->with($request, Symfony\Component\HttpKernel\HttpKernelInterface::MAIN_REQUEST, true)->andReturn($response); - $middleResponse = $middle->handle($request); - - $this->assertSame($response, $middleResponse); - } - - - public function testCheckingForRequestUsingArraySessions() - { - $middleware = new Illuminate\Session\Middleware( - m::mock(HttpKernelInterface::class), - $manager = m::mock(SessionManager::class), - function() { return true; } - ); - - $manager->shouldReceive('setDefaultDriver')->once()->with('array'); - - $middleware->checkRequestForArraySessions(new Symfony\Component\HttpFoundation\Request); - } - -} diff --git a/tests/Session/SessionStoreTest.php b/tests/Session/SessionStoreTest.php deleted file mode 100644 index 85553fcdd..000000000 --- a/tests/Session/SessionStoreTest.php +++ /dev/null @@ -1,329 +0,0 @@ -getSession(); - $session->getHandler()->shouldReceive('read')->once()->with($this->getSessionId())->andReturn( - serialize(['foo' => 'bar', 'bagged' => ['name' => 'taylor']]) - ); - $session->start(); - - $this->assertEquals('bar', $session->get('foo')); - $this->assertEquals('baz', $session->get('bar', 'baz')); - $this->assertTrue($session->has('foo')); - $this->assertFalse($session->has('bar')); - $this->assertTrue($session->isStarted()); - - $session->put('baz', 'boom'); - $this->assertTrue($session->has('baz')); - } - - - public function testExists() - { - $session = $this->getSession(); - $session->put('foo', 'bar'); - $session->put('baz', null); - - $this->assertTrue($session->exists('foo')); - $this->assertTrue($session->exists('baz')); - $this->assertTrue($session->exists(['foo', 'baz'])); - $this->assertFalse($session->exists(['foo', 'bar'])); - $this->assertFalse($session->exists('bar')); - - $this->assertTrue($session->has('foo')); - $this->assertFalse($session->has('baz')); - } - - - public function testSessionMigration() - { - $session = $this->getSession(); - $oldId = $session->getId(); - $session->getHandler()->shouldReceive('destroy')->never(); - $this->assertTrue($session->migrate()); - $this->assertNotEquals($oldId, $session->getId()); - - - $session = $this->getSession(); - $oldId = $session->getId(); - $session->getHandler()->shouldReceive('destroy')->once()->with($oldId); - $this->assertTrue($session->migrate(true)); - $this->assertNotEquals($oldId, $session->getId()); - } - - - public function testSessionRegeneration() - { - $session = $this->getSession(); - $oldId = $session->getId(); - $session->getHandler()->shouldReceive('destroy')->never(); - $this->assertTrue($session->regenerate()); - $this->assertNotEquals($oldId, $session->getId()); - } - - - public function testCantSetInvalidId() - { - $session = $this->getSession(); - - $session->setId(null); - $this->assertFalse(null == $session->getId()); - - $session->setId(['a']); - $this->assertFalse(['a'] == $session->getId()); - - $session->setId('wrong'); - $this->assertFalse('wrong' == $session->getId()); - } - - - public function testSessionInvalidate() - { - $session = $this->getSession(); - $oldId = $session->getId(); - $session->set('foo','bar'); - $this->assertGreaterThan(0, count($session->all())); - $session->getHandler()->shouldReceive('destroy')->never(); - $this->assertTrue($session->invalidate()); - $this->assertNotEquals($oldId, $session->getId()); - $this->assertCount(0, $session->all()); - } - - - public function testSessionIsProperlySaved() - { - $session = $this->getSession(); - $session->getHandler()->shouldReceive('read')->once()->andReturn(serialize([])); - $session->start(); - $session->put('foo', 'bar'); - $session->flash('baz', 'boom'); - $session->getHandler()->shouldReceive('write')->once()->with( - $this->getSessionId(), - serialize([ - '_token' => $session->token(), - 'foo' => 'bar', - 'baz' => 'boom', - 'flash' => [ - 'new' => [], - 'old' => ['baz'], - ], - ]) - ); - $session->save(); - - $this->assertFalse($session->isStarted()); - } - - - public function testOldInputFlashing() - { - $session = $this->getSession(); - $session->put('boom', 'baz'); - $session->flashInput(['foo' => 'bar', 'bar' => 0]); - - $this->assertTrue($session->hasOldInput('foo')); - $this->assertEquals('bar', $session->getOldInput('foo')); - $this->assertEquals(0, $session->getOldInput('bar')); - $this->assertFalse($session->hasOldInput('boom')); - - $session->ageFlashData(); - - $this->assertTrue($session->hasOldInput('foo')); - $this->assertEquals('bar', $session->getOldInput('foo')); - $this->assertEquals(0, $session->getOldInput('bar')); - $this->assertFalse($session->hasOldInput('boom')); - } - - - public function testDataFlashing() - { - $session = $this->getSession(); - $session->flash('foo', 'bar'); - $session->flash('bar', 0); - - $this->assertTrue($session->has('foo')); - $this->assertEquals('bar', $session->get('foo')); - $this->assertEquals(0, $session->get('bar')); - - $session->ageFlashData(); - - $this->assertTrue($session->has('foo')); - $this->assertEquals('bar', $session->get('foo')); - $this->assertEquals(0, $session->get('bar')); - - $session->ageFlashData(); - - $this->assertFalse($session->has('foo')); - $this->assertNull($session->get('foo')); - } - - - public function testDataMergeNewFlashes() - { - $session = $this->getSession(); - $session->flash('foo', 'bar'); - $session->set('fu', 'baz'); - $session->set('flash.old', ['qu']); - $this->assertNotFalse(array_search('foo', $session->get('flash.new'))); - $this->assertFalse(array_search('fu', $session->get('flash.new'))); - $session->keep(['fu','qu']); - $this->assertNotFalse(array_search('foo', $session->get('flash.new'))); - $this->assertNotFalse(array_search('fu', $session->get('flash.new'))); - $this->assertNotFalse(array_search('qu', $session->get('flash.new'))); - $this->assertFalse(array_search('qu', $session->get('flash.old'))); - } - - - public function testReflash() - { - $session = $this->getSession(); - $session->flash('foo', 'bar'); - $session->set('flash.old', ['foo']); - $session->reflash(); - $this->assertNotFalse(array_search('foo', $session->get('flash.new'))); - $this->assertFalse(array_search('foo', $session->get('flash.old'))); - } - - - public function testReplace() - { - $session = $this->getSession(); - $session->set('foo', 'bar'); - $session->set('qu', 'ux'); - $session->replace(['foo' => 'baz']); - $this->assertEquals('baz', $session->get('foo')); - $this->assertEquals('ux', $session->get('qu')); - } - - - public function testRemove() - { - $session = $this->getSession(); - $session->set('foo', 'bar'); - $pulled = $session->remove('foo'); - $this->assertFalse($session->has('foo')); - $this->assertEquals('bar', $pulled); - } - - - public function testFlush() - { - $session = $this->getSession(); - $session->put('foo', 'bar'); - - $session->flush(); - - $this->assertFalse($session->has('foo')); - $this->assertEmpty($session->all()); - } - - - public function testHasOldInputWithoutKey() - { - $session = $this->getSession(); - $session->flash('boom', 'baz'); - $this->assertFalse($session->hasOldInput()); - - $session->flashInput(['foo' => 'bar']); - $this->assertTrue($session->hasOldInput()); - } - - - public function testHandlerNeedsRequest() - { - $session = $this->getSession(); - $this->assertFalse($session->handlerNeedsRequest()); - $session->getHandler()->shouldReceive('setRequest')->never(); - - $session = new Store('test', m::mock(new CookieSessionHandler(new CookieJar(), 60))); - $this->assertTrue($session->handlerNeedsRequest()); - $session->getHandler()->shouldReceive('setRequest')->once(); - $request = new Request(); - $session->setRequestOnHandler($request); - } - - - public function testToken() - { - $session = $this->getSession(); - $this->assertEquals($session->token(), $session->getToken()); - } - - - public function testRegenerateToken() - { - $session = $this->getSession(); - $token = $session->getToken(); - $session->regenerateToken(); - $this->assertNotEquals($token, $session->getToken()); - } - - - public function testName() - { - $session = $this->getSession(); - $this->assertEquals($session->getName(), $this->getSessionName()); - $session->setName('foo'); - $this->assertEquals($session->getName(), 'foo'); - } - - - public function testSetPreviousUrl() - { - $session = $this->getSession(); - $session->setPreviousUrl('https://example.com/foo/bar'); - - $this->assertTrue($session->has('_previous.url')); - $this->assertSame('https://example.com/foo/bar', $session->get('_previous.url')); - - $url = $session->previousUrl(); - $this->assertSame('https://example.com/foo/bar', $url); - } - - - public function getSession() - { - $reflection = new ReflectionClass(Store::class); - return $reflection->newInstanceArgs($this->getMocks()); - } - - - public function getMocks() - { - return [ - $this->getSessionName(), - m::mock('SessionHandlerInterface'), - $this->getSessionId(), - ]; - } - - - public function getSessionId() - { - return 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; - } - - - public function getSessionName() - { - return 'name'; - } - -} diff --git a/tests/Support/SupportArrTest.php b/tests/Support/SupportArrTest.php index 164631d6f..971fc2a2c 100644 --- a/tests/Support/SupportArrTest.php +++ b/tests/Support/SupportArrTest.php @@ -155,7 +155,7 @@ public function testExists(): void $this->assertTrue(Arr::exists([null], 0)); $this->assertTrue(Arr::exists(['a' => 1], 'a')); $this->assertTrue(Arr::exists(['a' => null], 'a')); - $this->assertFalse(Arr::exists(new Collection(['a' => null]), 'a')); + $this->assertTrue(Arr::exists(new Collection(['a' => null]), 'a')); $this->assertFalse(Arr::exists([1], 1)); $this->assertFalse(Arr::exists([null], 1)); @@ -900,14 +900,6 @@ public function testSet(): void $this->assertEquals([1 => 'hAz'], Arr::set($array, 1, 'hAz')); } - public function testShuffleWithSeed(): void - { - $this->assertEquals( - Arr::shuffle(range(0, 100, 10), 1234), - Arr::shuffle(range(0, 100, 10), 1234) - ); - } - public function testSort(): void { $unsorted = [ diff --git a/tests/Support/SupportCollectionTest.php b/tests/Support/SupportCollectionTest.php index 3100ce368..6dd31818c 100755 --- a/tests/Support/SupportCollectionTest.php +++ b/tests/Support/SupportCollectionTest.php @@ -263,11 +263,11 @@ public function testChunk (): void } - public function testListsWithArrayAndObjectValues(): void + public function testPluckWithArrayAndObjectValues(): void { $data = new Collection([(object) ['name' => 'taylor', 'email' => 'foo'], ['name' => 'dayle', 'email' => 'bar']]); - $this->assertEquals(['taylor' => 'foo', 'dayle' => 'bar'], $data->lists('email', 'name')); - $this->assertEquals(['foo', 'bar'], $data->lists('email')); + $this->assertEquals(['taylor' => 'foo', 'dayle' => 'bar'], $data->pluck('email', 'name')->all()); + $this->assertEquals(['foo', 'bar'], $data->pluck('email')->all()); } @@ -340,13 +340,13 @@ public function testSplice(): void } - public function testGetListValueWithAccessors(): void + public function testGetPluckValueWithAccessors(): void { $model = new TestAccessorEloquentTestStub(['some' => 'foo']); $modelTwo = new TestAccessorEloquentTestStub(['some' => 'bar']); $data = new Collection([$model, $modelTwo]); - $this->assertEquals(['foo', 'bar'], $data->lists('some')); + $this->assertEquals(['foo', 'bar'], $data->pluck('some')->all()); } @@ -440,7 +440,7 @@ public function testValueRetrieverAcceptsDotNotation(): void ]); $c = $c->sortBy('foo.bar'); - $this->assertEquals([2, 1], $c->lists('id')); + $this->assertEquals([2, 1], $c->pluck('id')->all()); } @@ -516,6 +516,19 @@ public function __get($attribute) } + public function __isset($attribute) + { + $accessor = 'get'.lcfirst((string) $attribute).'Attribute'; + + if (method_exists($this, $accessor)) + { + return ! is_null($this->$accessor()); + } + + return isset($this->$attribute); + } + + public function getSomeAttribute() { return $this->attributes['some']; diff --git a/tests/Support/SupportFluentTest.php b/tests/Support/SupportFluentTest.php deleted file mode 100755 index df0039fc5..000000000 --- a/tests/Support/SupportFluentTest.php +++ /dev/null @@ -1,122 +0,0 @@ - 'Taylor', 'age' => 25]; - $fluent = new Fluent($array); - - $refl = new \ReflectionObject($fluent); - $attributes = $refl->getProperty('attributes'); - $attributes->setAccessible(true); - - $this->assertEquals($array, $attributes->getValue($fluent)); - $this->assertEquals($array, $fluent->getAttributes()); - } - - - public function testAttributesAreSetByConstructorGivenStdClass(): void - { - $array = ['name' => 'Taylor', 'age' => 25]; - $fluent = new Fluent((object) $array); - - $refl = new \ReflectionObject($fluent); - $attributes = $refl->getProperty('attributes'); - $attributes->setAccessible(true); - - $this->assertEquals($array, $attributes->getValue($fluent)); - $this->assertEquals($array, $fluent->getAttributes()); - } - - - public function testAttributesAreSetByConstructorGivenArrayIterator(): void - { - $array = ['name' => 'Taylor', 'age' => 25]; - $fluent = new Fluent(new FluentArrayIteratorStub($array)); - - $refl = new \ReflectionObject($fluent); - $attributes = $refl->getProperty('attributes'); - $attributes->setAccessible(true); - - $this->assertEquals($array, $attributes->getValue($fluent)); - $this->assertEquals($array, $fluent->getAttributes()); - } - - - public function testGetMethodReturnsAttribute(): void - { - $fluent = new Fluent(['name' => 'Taylor']); - - $this->assertEquals('Taylor', $fluent->get('name')); - $this->assertEquals('Default', $fluent->get('foo', 'Default')); - $this->assertEquals('Taylor', $fluent->name); - $this->assertNull($fluent->foo); - } - - - public function testMagicMethodsCanBeUsedToSetAttributes(): void - { - $fluent = new Fluent; - - $fluent->name = 'Taylor'; - $fluent->developer(); - $fluent->age(25); - - $this->assertEquals('Taylor', $fluent->name); - $this->assertTrue($fluent->developer); - $this->assertEquals(25, $fluent->age); - $this->assertInstanceOf(Fluent::class, $fluent->programmer()); - } - - - public function testIssetMagicMethod(): void - { - $array = ['name' => 'Taylor', 'age' => 25]; - $fluent = new Fluent($array); - - $this->assertTrue(isset($fluent->name)); - - unset($fluent->name); - - $this->assertFalse(isset($fluent->name)); - } - - - public function testToArrayReturnsAttribute(): void - { - $array = ['name' => 'Taylor', 'age' => 25]; - $fluent = new Fluent($array); - - $this->assertEquals($array, $fluent->toArray()); - } - - - public function testToJsonEncodesTheToArrayResult(): void - { - $fluent = $this->getMock(Fluent::class, ['toArray']); - $fluent->expects($this->once())->method('toArray')->willReturn('foo'); - $results = $fluent->toJson(); - - $this->assertEquals(json_encode('foo'), $results); - } - -} - - -class FluentArrayIteratorStub implements \IteratorAggregate { - protected array $items = []; - - public function __construct(array $items = []) - { - $this->items = (array) $items; - } - - public function getIterator(): Traversable - { - return new \ArrayIterator($this->items); - } -} diff --git a/tests/Support/SupportPluralizerTest.php b/tests/Support/SupportPluralizerTest.php deleted file mode 100755 index 8ef438f5a..000000000 --- a/tests/Support/SupportPluralizerTest.php +++ /dev/null @@ -1,53 +0,0 @@ -assertEquals('children', str_plural('child')); - $this->assertEquals('tests', str_plural('test')); - $this->assertEquals('deer', str_plural('deer')); - $this->assertEquals('child', str_singular('children')); - $this->assertEquals('test', str_singular('tests')); - $this->assertEquals('deer', str_singular('deer')); - $this->assertEquals('criterion', str_singular('criteria')); - } - - - public function testCaseSensitiveUsage() - { - $this->assertEquals('Children', str_plural('Child')); - $this->assertEquals('CHILDREN', str_plural('CHILD')); - $this->assertEquals('Tests', str_plural('Test')); - $this->assertEquals('TESTS', str_plural('TEST')); - $this->assertEquals('tests', str_plural('test')); - $this->assertEquals('Deer', str_plural('Deer')); - $this->assertEquals('DEER', str_plural('DEER')); - $this->assertEquals('Child', str_singular('Children')); - $this->assertEquals('CHILD', str_singular('CHILDREN')); - $this->assertEquals('Test', str_singular('Tests')); - $this->assertEquals('TEST', str_singular('TESTS')); - $this->assertEquals('Deer', str_singular('Deer')); - $this->assertEquals('DEER', str_singular('DEER')); - $this->assertEquals('Criterion', str_singular('Criteria')); - $this->assertEquals('CRITERION', str_singular('CRITERIA')); - } - - public function testIfEndOfWord() - { - $this->assertEquals('VortexFields', str_plural('VortexField')); - $this->assertEquals('MatrixFields', str_plural('MatrixField')); - $this->assertEquals('IndexFields', str_plural('IndexField')); - $this->assertEquals('VertexFields', str_plural('VertexField')); - } - - public function testAlreadyPluralizedIrregularWords() - { - $this->assertEquals('children', str_plural('children')); - $this->assertEquals('radii', str_plural('radii')); - $this->assertEquals('teeth', str_plural('teeth')); - } - -} diff --git a/tests/Support/SupportServiceProviderTest.php b/tests/Support/SupportServiceProviderTest.php deleted file mode 100755 index e14365992..000000000 --- a/tests/Support/SupportServiceProviderTest.php +++ /dev/null @@ -1,24 +0,0 @@ -assertEquals(realpath(__DIR__ . '/'), $superProvider->guessPackagePath()); - - $superSuperProvider = new SuperSuperProvider(null); - $this->assertEquals(realpath(__DIR__.'/'), $superSuperProvider->guessPackagePath()); - } - -} diff --git a/tests/Support/SupportStrTest.php b/tests/Support/SupportStrTest.php deleted file mode 100755 index 5dcdef2fa..000000000 --- a/tests/Support/SupportStrTest.php +++ /dev/null @@ -1,199 +0,0 @@ -assertEquals('Taylor...', Str::words('Taylor Otwell', 1)); - $this->assertEquals('Taylor___', Str::words('Taylor Otwell', 1, '___')); - $this->assertEquals('Taylor Otwell', Str::words('Taylor Otwell', 3)); - } - - - public function testStringTrimmedOnlyWhereNecessary(): void - { - $this->assertEquals(' Taylor Otwell ', Str::words(' Taylor Otwell ', 3)); - $this->assertEquals(' Taylor...', Str::words(' Taylor Otwell ', 1)); - } - - - public function testStringTitle(): void - { - $this->assertEquals('Jefferson Costella', Str::title('jefferson costella')); - $this->assertEquals('Jefferson Costella', Str::title('jefFErson coSTella')); - $this->assertEquals('Admin_Role', Str::title('admin_role')); - $this->assertEquals('', Str::title(null)); - $this->assertEquals('', Str::title('')); - } - - - public function testStringWithoutWordsDoesntProduceError(): void - { - $nbsp = chr(0xC2).chr(0xA0); - $this->assertEquals(' ', Str::words(' ')); - $this->assertEquals($nbsp, Str::words($nbsp)); - } - - - public function testStartsWith(): void - { - $this->assertTrue(Str::startsWith('jason', 'jas')); - $this->assertTrue(Str::startsWith('jason', 'jason')); - $this->assertTrue(Str::startsWith('jason', ['jas'])); - $this->assertFalse(Str::startsWith('jason', 'day')); - $this->assertFalse(Str::startsWith('jason', ['day'])); - $this->assertFalse(Str::startsWith('jason', '')); - } - - public function testEquals(): void - { - self::assertTrue(Str::equals('1234', '1234')); - self::assertTrue(Str::equals('Laravel', 'Laravel')); - self::assertTrue(Str::equals('Laravel', 'laRaVeL')); - self::assertFalse(Str::equals('Laravel', 'laRaVeL', true)); - self::assertTrue(Str::equals('', '')); - self::assertTrue(Str::equals('', null)); - self::assertTrue(Str::equals()); - self::assertFalse(Str::equals(null, 'Laravel')); - self::assertFalse(Str::equals('Laravel')); - self::assertFalse(Str::equals('Laravel', null, true)); - } - - - public function testEndsWith(): void - { - $this->assertTrue(Str::endsWith('jason', 'on')); - $this->assertTrue(Str::endsWith('jason', 'jason')); - $this->assertTrue(Str::endsWith('jason', ['on'])); - $this->assertFalse(Str::endsWith('jason', 'no')); - $this->assertFalse(Str::endsWith('jason', ['no'])); - $this->assertFalse(Str::endsWith('jason', '')); - $this->assertFalse(Str::endsWith('7', ' 7')); - } - - - public function testStrContains(): void - { - $this->assertTrue(Str::contains('taylor', 'ylo')); - $this->assertTrue(Str::contains('taylor', ['ylo'])); - $this->assertFalse(Str::contains('taylor', 'xxx')); - $this->assertFalse(Str::contains('taylor', ['xxx'])); - $this->assertFalse(Str::contains('taylor', '')); - $this->assertFalse(Str::contains('taylor', null)); - $this->assertFalse(Str::contains('', 'y')); - $this->assertFalse(Str::contains(null, 'y')); - } - - - public function testParseCallback(): void - { - $this->assertEquals(['Class', 'method'], Str::parseCallback('Class@method', 'foo')); - $this->assertEquals(['Class', 'foo'], Str::parseCallback('Class', 'foo')); - } - - - public function testSlug(): void - { - $this->assertEquals('hello-world', Str::slug('hello world')); - $this->assertEquals('hello-world', Str::slug('hello-world')); - $this->assertEquals('hello-world', Str::slug('hello_world')); - $this->assertEquals('hello_world', Str::slug('hello_world', '_')); - } - - - public function testFinish(): void - { - $this->assertEquals('abbc', Str::finish('ab', 'bc')); - $this->assertEquals('abbc', Str::finish('abbcbc', 'bc')); - $this->assertEquals('abcbbc', Str::finish('abcbbcbc', 'bc')); - } - - - public function testIs(): void - { - $this->assertTrue(Str::is('/', '/')); - $this->assertFalse(Str::is('/', ' /')); - $this->assertFalse(Str::is('/', '/a')); - $this->assertTrue(Str::is('foo/*', 'foo/bar/baz')); - $this->assertTrue(Str::is('*/foo', 'blah/baz/foo')); - $this->assertFalse(Str::is('*/foo', '')); - $this->assertFalse(Str::is('*/foo', null)); - } - - - public function testLower(): void - { - $this->assertEquals('foo bar baz', Str::lower('FOO BAR BAZ')); - $this->assertEquals('foo bar baz', Str::lower('fOo Bar bAz')); - $this->assertEquals('', Str::lower(null)); - } - - - public function testUpper(): void - { - $this->assertEquals('FOO BAR BAZ', Str::upper('foo bar baz')); - $this->assertEquals('FOO BAR BAZ', Str::upper('foO bAr BaZ')); - $this->assertEquals('', Str::upper(null)); - } - - - public function testLimit(): void - { - $this->assertEquals('Laravel is...', Str::limit('Laravel is a free, open source PHP web application framework.', 10)); - $this->assertEquals('', Str::limit(null)); - $this->assertEquals('', Str::limit('')); - } - - - public function testLength(): void - { - $this->assertEquals(11, Str::length('foo bar baz')); - $this->assertEquals(0, Str::length('')); - $this->assertEquals(0, Str::length(null)); - } - - - public function testQuickRandom(): void - { - $randomInteger = mt_rand(1, 100); - $this->assertEquals($randomInteger, strlen(Str::quickRandom($randomInteger))); - $this->assertIsString(Str::quickRandom()); - $this->assertEquals(16, strlen(Str::quickRandom())); - } - - - public function testRandom(): void - { - $this->assertEquals(16, strlen(Str::random())); - $randomInteger = mt_rand(1, 100); - $this->assertEquals($randomInteger, strlen(Str::random($randomInteger))); - $this->assertIsString(Str::random()); - } - - public function testNumberFormat(): void - { - $this->assertEquals('1,000,000', Str::numberFormat(1000000)); - $this->assertEquals('150.000,00', Str::numberFormat(150000, 2, ',', '.')); - $this->assertEquals('0', Str::numberFormat()); - $this->assertEquals('0', Str::numberFormat(null)); - } - - public function testReplace(): void - { - $this->assertSame('foo bar laravel', Str::replace('baz', 'laravel', 'foo bar baz')); - $this->assertSame('foo bar baz 8.x', Str::replace('?', '8.x', 'foo bar baz ?')); - $this->assertSame('foo/bar/baz', Str::replace(' ', '/', 'foo bar baz')); - $this->assertSame('foo bar baz', Str::replace(['?1', '?2', '?3'], ['foo', 'bar', 'baz'], '?1 ?2 ?3')); - $this->assertEquals('', Str::replace('Yo', 'Laravel', '')); - $this->assertEquals('', Str::replace('Yo', 'Laravel', null)); - } -} diff --git a/tests/Support/SupportUtilTest.php b/tests/Support/SupportUtilTest.php index 016058b15..b6d237dd3 100644 --- a/tests/Support/SupportUtilTest.php +++ b/tests/Support/SupportUtilTest.php @@ -2,7 +2,6 @@ namespace Illuminate\Tests\Support; -use Illuminate\Pagination\Factory; use Illuminate\Pagination\Paginator; use Illuminate\Support\Util; use L4\Tests\BackwardCompatibleTestCase; @@ -42,11 +41,7 @@ public function isValueEmpty(): void */ public function isEmptyOnEmptyPaginatorObject(): void { - $pagination = new Paginator( - $this->prophesize(Factory::class)->reveal(), - [], - 0 - ); + $pagination = new Paginator([], 15); $this->assertTrue(Util::isEmpty($pagination)); } @@ -56,11 +51,7 @@ public function isEmptyOnEmptyPaginatorObject(): void */ public function isEmptyOnNonEmptyPaginatorObject(): void { - $pagination = new Paginator( - $this->prophesize(Factory::class)->reveal(), - ['1', '2', '3'], - 3 - ); + $pagination = new Paginator(['1', '2', '3'], 15); $this->assertFalse(Util::isEmpty($pagination)); } diff --git a/tests/View/ViewBladeCompilerTest.php b/tests/View/ViewBladeCompilerTest.php deleted file mode 100644 index 5ac6efd3d..000000000 --- a/tests/View/ViewBladeCompilerTest.php +++ /dev/null @@ -1,627 +0,0 @@ -compiler = new BladeCompiler($this->getFiles(), __DIR__); - } - - protected function tearDown(): void - { - m::close(); - } - - - public function testIsExpiredReturnsTrueIfCompiledFileDoesntExist() - { - $compiler = new BladeCompiler($files = $this->getFiles(), __DIR__); - $files->shouldReceive('exists')->once()->with(__DIR__ . '/' . md5('foo'))->andReturn(false); - $this->assertTrue($compiler->isExpired('foo')); - } - - - public function testIsExpiredReturnsTrueIfCachePathIsNull() - { - $compiler = new BladeCompiler($files = $this->getFiles(), null); - $files->shouldReceive('exists')->never(); - $this->assertTrue($compiler->isExpired('foo')); - } - - - public function testIsExpiredReturnsTrueWhenModificationTimesWarrant() - { - $compiler = new BladeCompiler($files = $this->getFiles(), __DIR__); - $files->shouldReceive('exists')->once()->with(__DIR__.'/'.md5('foo'))->andReturn(true); - $files->shouldReceive('lastModified')->once()->with('foo')->andReturn(100); - $files->shouldReceive('lastModified')->once()->with(__DIR__.'/'.md5('foo'))->andReturn(0); - $this->assertTrue($compiler->isExpired('foo')); - } - - - public function testCompilePathIsProperlyCreated() - { - $compiler = new BladeCompiler($this->getFiles(), __DIR__); - $this->assertEquals(__DIR__.'/'.md5('foo'), $compiler->getCompiledPath('foo')); - } - - - public function testCompileCompilesFileAndReturnsContents() - { - $compiler = new BladeCompiler($files = $this->getFiles(), __DIR__); - $files->shouldReceive('get')->once()->with('foo')->andReturn('Hello World'); - $files->shouldReceive('put')->once()->with(__DIR__.'/'.md5('foo'), 'Hello World'); - $compiler->compile('foo'); - } - - - public function testCompileCompilesAndGetThePath() - { - $compiler = new BladeCompiler($files = $this->getFiles(), __DIR__); - $files->shouldReceive('get')->once()->with('foo')->andReturn('Hello World'); - $files->shouldReceive('put')->once()->with(__DIR__.'/'.md5('foo'), 'Hello World'); - $compiler->compile('foo'); - $this->assertEquals('foo', $compiler->getPath()); - } - - - public function testCompileSetAndGetThePath() - { - $compiler = new BladeCompiler($files = $this->getFiles(), __DIR__); - $compiler->setPath('foo'); - $this->assertEquals('foo', $compiler->getPath()); - } - - - public function testCompileDoesntStoreFilesWhenCachePathIsNull() - { - $compiler = new BladeCompiler($files = $this->getFiles(), null); - $files->shouldReceive('get')->once()->with('foo')->andReturn('Hello World'); - $files->shouldReceive('put')->never(); - $compiler->compile('foo'); - } - - - public function testEchosAreCompiled() - { - $this->assertEquals('', $this->compiler->compileString('{{{$name}}}')); - $this->assertEquals('', $this->compiler->compileString('{{$name}}')); - $this->assertEquals('', $this->compiler->compileString('{{ $name }}')); - $this->assertEquals('', $this->compiler->compileString('{{ - $name - }}')); - $this->assertEquals("\n\n", $this->compiler->compileString("{{ \$name }}\n")); - $this->assertEquals("\r\n\r\n", $this->compiler->compileString("{{ \$name }}\r\n")); - $this->assertEquals("\n\n", $this->compiler->compileString("{{ \$name }}\n")); - $this->assertEquals("\r\n\r\n", $this->compiler->compileString("{{ \$name }}\r\n")); - - $this->assertEquals('', $this->compiler->compileString('{{ $name or "foo" }}')); - $this->assertEquals('name) ? $user->name : "foo"; ?>', $this->compiler->compileString('{{ $user->name or "foo" }}')); - $this->assertEquals('', $this->compiler->compileString('{{$name or "foo"}}')); - $this->assertEquals('', $this->compiler->compileString('{{ - $name or "foo" - }}')); - - $this->assertEquals('', $this->compiler->compileString('{{ $name or \'foo\' }}')); - $this->assertEquals('', $this->compiler->compileString('{{$name or \'foo\'}}')); - $this->assertEquals('', $this->compiler->compileString('{{ - $name or \'foo\' - }}')); - - $this->assertEquals('', $this->compiler->compileString('{{ $age or 90 }}')); - $this->assertEquals('', $this->compiler->compileString('{{$age or 90}}')); - $this->assertEquals('', $this->compiler->compileString('{{ - $age or 90 - }}')); - - $this->assertEquals('', $this->compiler->compileString('{{ "Hello world or foo" }}')); - $this->assertEquals('', $this->compiler->compileString('{{"Hello world or foo"}}')); - $this->assertEquals('', $this->compiler->compileString('{{$foo + $or + $baz}}')); - $this->assertEquals('', $this->compiler->compileString('{{ - "Hello world or foo" - }}')); - - $this->assertEquals('', $this->compiler->compileString('{{ \'Hello world or foo\' }}')); - $this->assertEquals('', $this->compiler->compileString('{{\'Hello world or foo\'}}')); - $this->assertEquals('', $this->compiler->compileString('{{ - \'Hello world or foo\' - }}')); - - $this->assertEquals('', $this->compiler->compileString('{{ myfunc(\'foo or bar\') }}')); - $this->assertEquals('', $this->compiler->compileString('{{ myfunc("foo or bar") }}')); - $this->assertEquals('', $this->compiler->compileString('{{ myfunc("$name or \'foo\'") }}')); - } - - - public function testEscapedWithAtEchosAreCompiled() - { - $this->assertEquals('{{$name}}', $this->compiler->compileString('@{{$name}}')); - $this->assertEquals('{{ $name }}', $this->compiler->compileString('@{{ $name }}')); - $this->assertEquals('{{ - $name - }}', - $this->compiler->compileString('@{{ - $name - }}')); - $this->assertEquals('{{ $name }} - ', - $this->compiler->compileString('@{{ $name }} - ')); - } - - - public function testReversedEchosAreCompiled() - { - $this->compiler->setEscapedContentTags('{{', '}}'); - $this->compiler->setContentTags('{{{', '}}}'); - $this->assertEquals('', $this->compiler->compileString('{{$name}}')); - $this->assertEquals('', $this->compiler->compileString('{{{$name}}}')); - $this->assertEquals('', $this->compiler->compileString('{{{ $name }}}')); - $this->assertEquals('', $this->compiler->compileString('{{{ - $name - }}}')); - } - - - public function testExtendsAreCompiled() - { - $compiler = new BladeCompiler($this->getFiles(), __DIR__); - $string = '@extends(\'foo\') -test'; - $expected = "test".PHP_EOL.'make(\'foo\', array_except(get_defined_vars(), array(\'__data\', \'__path\')))->render(); ?>'; - $this->assertEquals($expected, $compiler->compileString($string)); - - - $compiler = new BladeCompiler($this->getFiles(), __DIR__); - $string = '@extends(name(foo))'.PHP_EOL.'test'; - $expected = "test".PHP_EOL.'make(name(foo), array_except(get_defined_vars(), array(\'__data\', \'__path\')))->render(); ?>'; - $this->assertEquals($expected, $compiler->compileString($string)); - } - - - public function testPushIsCompiled() - { - $string = '@push(\'foo\') -test -@endpush'; - $expected = 'startSection(\'foo\'); ?> -test -appendSection(); ?>'; - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testStackIsCompiled() - { - $string = '@stack(\'foo\')'; - $expected = 'yieldContent(\'foo\'); ?>'; - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testCommentsAreCompiled() - { - $string = '{{--this is a comment--}}'; - $expected = ''; - $this->assertEquals($expected, $this->compiler->compileString($string)); - - - $string = '{{-- -this is a comment ---}}'; - $expected = ''; - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testIfStatementsAreCompiled() - { - $string = '@if (name(foo(bar))) -breeze -@endif'; - $expected = ' -breeze -'; - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testElseStatementsAreCompiled() - { - $string = '@if (name(foo(bar))) -breeze -@else -boom -@endif'; - $expected = ' -breeze - -boom -'; - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testElseIfStatementsAreCompiled() - { - $string = '@if(name(foo(bar))) -breeze -@elseif(boom(breeze)) -boom -@endif'; - $expected = ' -breeze - -boom -'; - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testUnlessStatementsAreCompiled() - { - $string = '@unless (name(foo(bar))) -breeze -@endunless'; - $expected = ' -breeze -'; - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testForelseStatementsAreCompiled() - { - $string = '@forelse ($this->getUsers() as $user) -breeze -@empty -empty -@endforelse'; - $expected = 'getUsers() as $user): $__empty_1 = false; ?> -breeze - -empty -'; - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testNestedForelseStatementsAreCompiled() - { - $string = '@forelse ($this->getUsers() as $user) -@forelse ($user->tags as $tag) -breeze -@empty -tag empty -@endforelse -@empty -empty -@endforelse'; - $expected = 'getUsers() as $user): $__empty_1 = false; ?> -tags as $tag): $__empty_2 = false; ?> -breeze - -tag empty - - -empty -'; - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testStatementThatContainsNonConsecutiveParanthesisAreCompiled() - { - $string = "Foo @lang(function_call('foo(blah)')) bar"; - $expected = "Foo bar"; - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testIncludesAreCompiled() - { - $this->assertEquals('make(\'foo\', array_except(get_defined_vars(), array(\'__data\', \'__path\')))->render(); ?>', $this->compiler->compileString('@include(\'foo\')')); - $this->assertEquals('make(name(foo), array_except(get_defined_vars(), array(\'__data\', \'__path\')))->render(); ?>', $this->compiler->compileString('@include(name(foo))')); - } - - - public function testShowEachAreCompiled() - { - $this->assertEquals('renderEach(\'foo\', \'bar\'); ?>', $this->compiler->compileString('@each(\'foo\', \'bar\')')); - $this->assertEquals('renderEach(name(foo)); ?>', $this->compiler->compileString('@each(name(foo))')); - } - - - public function testYieldsAreCompiled() - { - $this->assertEquals('yieldContent(\'foo\'); ?>', $this->compiler->compileString('@yield(\'foo\')')); - $this->assertEquals('yieldContent(\'foo\', \'bar\'); ?>', $this->compiler->compileString('@yield(\'foo\', \'bar\')')); - $this->assertEquals('yieldContent(name(foo)); ?>', $this->compiler->compileString('@yield(name(foo))')); - } - - - public function testShowsAreCompiled() - { - $this->assertEquals('yieldSection(); ?>', $this->compiler->compileString('@show')); - } - - - public function testLanguageAndChoicesAreCompiled() - { - $this->assertEquals('', $this->compiler->compileString("@lang('foo')")); - $this->assertEquals('', $this->compiler->compileString("@choice('foo', 1)")); - } - - - public function testSectionStartsAreCompiled() - { - $this->assertEquals('startSection(\'foo\'); ?>', $this->compiler->compileString('@section(\'foo\')')); - $this->assertEquals('startSection(name(foo)); ?>', $this->compiler->compileString('@section(name(foo))')); - } - - - public function testStopSectionsAreCompiled() - { - $this->assertEquals('stopSection(); ?>', $this->compiler->compileString('@stop')); - } - - - public function testEndSectionsAreCompiled() - { - $this->assertEquals('stopSection(); ?>', $this->compiler->compileString('@endsection')); - } - - - public function testAppendSectionsAreCompiled() - { - $this->assertEquals('appendSection(); ?>', $this->compiler->compileString('@append')); - } - - - public function testCustomPhpCodeIsCorrectlyHandled() - { - $this->assertEquals(' ', $this->compiler->compileString("@if(\$test) @endif")); - } - - - public function testMixingYieldAndEcho() - { - $this->assertEquals('yieldContent(\'title\'); ?> - ', $this->compiler->compileString("@yield('title') - {{Config::get('site.title')}}")); - } - - - public function testCustomExtensionsAreCompiled() - { - $this->compiler->extend(function($value) { return str_replace('foo', 'bar', $value); }); - $this->assertEquals('bar', $this->compiler->compileString('foo')); - } - - - public function testConfiguringContentTags() - { - $this->compiler->setContentTags('[[', ']]'); - $this->compiler->setEscapedContentTags('[[[', ']]]'); - - $this->assertEquals('', $this->compiler->compileString('[[[ $name ]]]')); - $this->assertEquals('', $this->compiler->compileString('[[ $name ]]')); - $this->assertEquals('', $this->compiler->compileString('[[ - $name - ]]')); - } - - - public function testExpressionsOnTheSameLine() - { - $this->assertEquals(' space () ', $this->compiler->compileString('@lang(foo(bar(baz(qux(breeze()))))) space () @lang(foo(bar))')); - } - - - public function testExpressionWithinHTML() - { - $this->assertEquals('>', $this->compiler->compileString('')); - $this->assertEquals('>', $this->compiler->compileString('')); - $this->assertEquals(' >', $this->compiler->compileString('')); - } - - - public function testSelectedStatementsAreCompiled() - { - $string = ''; - $expected = "/>"; - - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testCheckedStatementsAreCompiled() - { - $string = ''; - $expected = "/>"; - - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testDisabledStatementsAreCompiled() - { - $string = ''; - $expected = ""; - - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testClassesAreConditionallyCompiledFromArray() - { - $string = " true, 'mr-2' => false])>"; - $expected = " true, 'mr-2' => false])); ?>\">"; - - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testJsonIsCompiledWithSafeDefaultEncodingOptions() - { - $string = 'var foo = @json($var);'; - $expected = 'var foo = ;'; - - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testEnvStatementsAreCompiled() - { - $string = "@env('staging') -breeze -@else -boom -@endenv"; - $expected = "environment('staging')): ?> -breeze - -boom -"; - - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testEnvStatementsWithMultipleStringParamsAreCompiled() - { - $string = "@env('staging', 'production') -breeze -@else -boom -@endenv"; - $expected = "environment('staging', 'production')): ?> -breeze - -boom -"; - - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testEnvStatementsWithArrayParamAreCompiled() - { - $string = "@env(['staging', 'production']) -breeze -@else -boom -@endenv"; - $expected = "environment(['staging', 'production'])): ?> -breeze - -boom -"; - - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testProductionEnvStatementsAreCompiled() - { - $string = "@production -breeze -@else -boom -@endproduction"; - $expected = "environment('production')): ?> -breeze - -boom -"; - - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testPlainAuthIfStatementsAreCompiled() - { - $string = '@auth -breeze -@endauth'; - $expected = ' -breeze -'; - - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - public function testPlainGuestIfStatementsAreCompiled() - { - $string = '@guest -breeze -@endguest'; - $expected = ' -breeze -'; - - $this->assertEquals($expected, $this->compiler->compileString($string)); - } - - - protected function getFiles() - { - return m::mock('Illuminate\Filesystem\Filesystem'); - } - - - public function testRetrieveDefaultContentTags() - { - $this->assertEquals(['{{', '}}'], $this->compiler->getContentTags()); - } - - - public function testRetrieveDefaultEscapedContentTags() - { - $this->assertEquals(['{{{', '}}}'], $this->compiler->getEscapedContentTags()); - } - - - /** - * @dataProvider testGetTagsProvider() - */ - public function testSetAndRetrieveContentTags($openingTag, $closingTag) - { - $this->compiler->setContentTags($openingTag, $closingTag); - $this->assertSame([$openingTag, $closingTag], $this->compiler->getContentTags()); - } - - - /** - * @dataProvider testGetTagsProvider() - */ - public function testSetAndRetrieveEscapedContentTags($openingTag, $closingTag) - { - $this->compiler->setEscapedContentTags($openingTag, $closingTag); - $this->assertSame([$openingTag, $closingTag], $this->compiler->getEscapedContentTags()); - } - - - public function testGetTagsProvider() - { - return [ - ['{{', '}}'], - ['{{{', '}}}'], - ['[[', ']]'], - ['[[[', ']]]'], - ['((', '))'], - ['(((', ')))'], - ]; - } - -} diff --git a/tests/View/ViewCompilerEngineTest.php b/tests/View/ViewCompilerEngineTest.php deleted file mode 100755 index 0d388ee5c..000000000 --- a/tests/View/ViewCompilerEngineTest.php +++ /dev/null @@ -1,50 +0,0 @@ -getEngine(); - $engine->getCompiler()->shouldReceive('getCompiledPath')->with(__DIR__ . '/fixtures/foo.php')->andReturn( - __DIR__ . '/fixtures/basic.php' - ); - $engine->getCompiler()->shouldReceive('isExpired')->once()->with(__DIR__ . '/fixtures/foo.php')->andReturn( - true - ); - $engine->getCompiler()->shouldReceive('compile')->once()->with(__DIR__.'/fixtures/foo.php'); - $results = $engine->get(__DIR__.'/fixtures/foo.php'); - - $this->assertEquals("Hello World\n", $results); - } - - - public function testViewsAreNotRecompiledIfTheyAreNotExpired() - { - $engine = $this->getEngine(); - $engine->getCompiler()->shouldReceive('getCompiledPath')->with(__DIR__.'/fixtures/foo.php')->andReturn(__DIR__.'/fixtures/basic.php'); - $engine->getCompiler()->shouldReceive('isExpired')->once()->andReturn(false); - $engine->getCompiler()->shouldReceive('compile')->never(); - $results = $engine->get(__DIR__.'/fixtures/foo.php'); - - $this->assertEquals("Hello World\n", $results); - } - - - protected function getEngine() - { - return new CompilerEngine(m::mock(CompilerInterface::class)); - } - -} diff --git a/tests/View/ViewEngineResolverTest.php b/tests/View/ViewEngineResolverTest.php deleted file mode 100755 index 92d5d9976..000000000 --- a/tests/View/ViewEngineResolverTest.php +++ /dev/null @@ -1,24 +0,0 @@ -register('foo', function() { return new StdClass; }); - $result = $resolver->resolve('foo'); - - $this->assertEquals(spl_object_hash($result), spl_object_hash($resolver->resolve('foo'))); - } - - - public function testResolverThrowsExceptionOnUnknownEngine() - { - $this->expectException('InvalidArgumentException'); - $resolver = new Illuminate\View\Engines\EngineResolver; - $resolver->resolve('foo'); - } - -} diff --git a/tests/View/ViewFactoryTest.php b/tests/View/ViewFactoryTest.php deleted file mode 100755 index 83ee781b3..000000000 --- a/tests/View/ViewFactoryTest.php +++ /dev/null @@ -1,378 +0,0 @@ -getFactory(); - $factory->getFinder()->shouldReceive('find')->once()->with('view')->andReturn('path.php'); - $factory->getEngineResolver()->shouldReceive('resolve')->once()->with('php')->andReturn($engine = m::mock( - EngineInterface::class - )); - $factory->getFinder()->shouldReceive('addExtension')->once()->with('php'); - $factory->setDispatcher(new Illuminate\Events\Dispatcher); - $factory->creator('view', function($view) { $_SERVER['__test.view'] = $view; }); - $factory->addExtension('php', 'php'); - $view = $factory->make('view', ['foo' => 'bar'], ['baz' => 'boom']); - - $this->assertSame($engine, $view->getEngine()); - $this->assertSame($_SERVER['__test.view'], $view); - - unset($_SERVER['__test.view']); - } - - - public function testExistsPassesAndFailsViews() - { - $factory = $this->getFactory(); - $factory->getFinder()->shouldReceive('find')->once()->with('foo')->andThrow('InvalidArgumentException'); - $factory->getFinder()->shouldReceive('find')->once()->with('bar')->andReturn('path.php'); - - $this->assertFalse($factory->exists('foo')); - $this->assertTrue($factory->exists('bar')); - } - - - public function testRenderEachCreatesViewForEachItemInArray() - { - $factory = m::mock('Illuminate\View\Factory[make]', $this->getFactoryArgs()); - $factory->shouldReceive('make')->once()->with('foo', ['key' => 'bar', 'value' => 'baz'])->andReturn($mockView1 = m::mock('StdClass')); - $factory->shouldReceive('make')->once()->with('foo', ['key' => 'breeze', 'value' => 'boom'])->andReturn($mockView2 = m::mock('StdClass')); - $mockView1->shouldReceive('render')->once()->andReturn('dayle'); - $mockView2->shouldReceive('render')->once()->andReturn('rees'); - - $result = $factory->renderEach('foo', ['bar' => 'baz', 'breeze' => 'boom'], 'value'); - - $this->assertEquals('daylerees', $result); - } - - - public function testEmptyViewsCanBeReturnedFromRenderEach() - { - $factory = m::mock('Illuminate\View\Factory[make]', $this->getFactoryArgs()); - $factory->shouldReceive('make')->once()->with('foo')->andReturn($mockView = m::mock('StdClass')); - $mockView->shouldReceive('render')->once()->andReturn('empty'); - - $this->assertEquals('empty', $factory->renderEach('view', [], 'iterator', 'foo')); - } - - - public function testRawStringsMayBeReturnedFromRenderEach() - { - $this->assertEquals('foo', $this->getFactory()->renderEach('foo', [], 'item', 'raw|foo')); - } - - - public function testEnvironmentAddsExtensionWithCustomResolver() - { - $factory = $this->getFactory(); - - $resolver = function(){}; - - $factory->getFinder()->shouldReceive('addExtension')->once()->with('foo'); - $factory->getEngineResolver()->shouldReceive('register')->once()->with('bar', $resolver); - $factory->getFinder()->shouldReceive('find')->once()->with('view')->andReturn('path.foo'); - $factory->getEngineResolver()->shouldReceive('resolve')->once()->with('bar')->andReturn($engine = m::mock( - EngineInterface::class - )); - $factory->getDispatcher()->shouldReceive('dispatch'); - - $factory->addExtension('foo', 'bar', $resolver); - - $view = $factory->make('view', ['data']); - $this->assertSame($engine, $view->getEngine()); - } - - - public function testAddingExtensionPrependsNotAppends() - { - $factory = $this->getFactory(); - $factory->getFinder()->shouldReceive('addExtension')->once()->with('foo'); - - $factory->addExtension('foo', 'bar'); - - $extensions = $factory->getExtensions(); - $this->assertEquals('bar', reset($extensions)); - $this->assertEquals('foo', key($extensions)); - } - - - public function testPrependedExtensionOverridesExistingExtensions() - { - $factory = $this->getFactory(); - $factory->getFinder()->shouldReceive('addExtension')->once()->with('foo'); - $factory->getFinder()->shouldReceive('addExtension')->once()->with('baz'); - - $factory->addExtension('foo', 'bar'); - $factory->addExtension('baz', 'bar'); - - $extensions = $factory->getExtensions(); - $this->assertEquals('bar', reset($extensions)); - $this->assertEquals('baz', key($extensions)); - } - - - public function testComposersAreProperlyRegistered() - { - $factory = $this->getFactory(); - $factory->getDispatcher()->shouldReceive('listen')->once()->with('composing: foo', m::type('Closure')); - $callback = $factory->composer('foo', function() { return 'bar'; }); - $callback = $callback[0]; - - $this->assertEquals('bar', $callback()); - } - - - public function testComposersAreProperlyRegisteredWithPriority() - { - $factory = $this->getFactory(); - $factory->getDispatcher()->shouldReceive('listen')->once()->with('composing: foo', m::type('Closure'), 1); - $callback = $factory->composer('foo', function() { return 'bar'; }, 1); - $callback = $callback[0]; - - $this->assertEquals('bar', $callback()); - } - - - public function testComposersCanBeMassRegistered() - { - $factory = $this->getFactory(); - $factory->getDispatcher()->shouldReceive('listen')->once()->with('composing: bar', m::type('Closure')); - $factory->getDispatcher()->shouldReceive('listen')->once()->with('composing: qux', m::type('Closure')); - $factory->getDispatcher()->shouldReceive('listen')->once()->with('composing: foo', m::type('Closure')); - $composers = $factory->composers([ - 'foo' => 'bar', - 'baz@baz' => ['qux', 'foo'], - ]); - - $this->assertCount(3, $composers); - $reflections = [ - new ReflectionFunction($composers[0]), - new ReflectionFunction($composers[1]), - ]; - $this->assertEquals(['class' => 'foo', 'method' => 'compose', 'container' => null], $reflections[0]->getStaticVariables()); - $this->assertEquals(['class' => 'baz', 'method' => 'baz', 'container' => null], $reflections[1]->getStaticVariables()); - } - - - public function testClassCallbacks() - { - $factory = $this->getFactory(); - $factory->getDispatcher()->shouldReceive('listen')->once()->with('composing: foo', m::type('Closure')); - $factory->setContainer($container = m::mock(Container::class)); - $container->shouldReceive('make')->once()->with('FooComposer')->andReturn($composer = m::mock('StdClass')); - $composer->shouldReceive('compose')->once()->with('view')->andReturn('composed'); - $callback = $factory->composer('foo', 'FooComposer'); - $callback = $callback[0]; - - $this->assertEquals('composed', $callback('view')); - } - - - public function testClassCallbacksWithMethods() - { - $factory = $this->getFactory(); - $factory->getDispatcher()->shouldReceive('listen')->once()->with('composing: foo', m::type('Closure')); - $factory->setContainer($container = m::mock(Container::class)); - $container->shouldReceive('make')->once()->with('FooComposer')->andReturn($composer = m::mock('StdClass')); - $composer->shouldReceive('doComposer')->once()->with('view')->andReturn('composed'); - $callback = $factory->composer('foo', 'FooComposer@doComposer'); - $callback = $callback[0]; - - $this->assertEquals('composed', $callback('view')); - } - - - public function testCallComposerCallsProperEvent() - { - $factory = $this->getFactory(); - $view = m::mock(View::class); - $view->shouldReceive('getName')->once()->andReturn('name'); - $factory->getDispatcher()->shouldReceive('dispatch')->once()->with('composing: name', [$view]); - - $factory->callComposer($view); - } - - - public function testRenderCountHandling() - { - $factory = $this->getFactory(); - $factory->incrementRender(); - $this->assertFalse($factory->doneRendering()); - $factory->decrementRender(); - $this->assertTrue($factory->doneRendering()); - } - - - public function testBasicSectionHandling() - { - $factory = $this->getFactory(); - $factory->startSection('foo'); - echo 'hi'; - $factory->stopSection(); - $this->assertEquals('hi', $factory->yieldContent('foo')); - } - - - public function testSectionExtending() - { - $factory = $this->getFactory(); - $factory->startSection('foo'); - echo 'hi @parent'; - $factory->stopSection(); - $factory->startSection('foo'); - echo 'there'; - $factory->stopSection(); - $this->assertEquals('hi there', $factory->yieldContent('foo')); - } - - - public function testSingleStackPush() - { - $factory = $this->getFactory(); - $factory->startSection('foo'); - echo 'hi'; - $factory->appendSection(); - $this->assertEquals('hi', $factory->yieldContent('foo')); - } - - - public function testMultipleStackPush() - { - $factory = $this->getFactory(); - $factory->startSection('foo'); - echo 'hi'; - $factory->appendSection(); - $factory->startSection('foo'); - echo ', Hello!'; - $factory->appendSection(); - $this->assertEquals('hi, Hello!', $factory->yieldContent('foo')); - } - - - public function testSessionAppending() - { - $factory = $this->getFactory(); - $factory->startSection('foo'); - echo 'hi'; - $factory->appendSection(); - $factory->startSection('foo'); - echo 'there'; - $factory->appendSection(); - $this->assertEquals('hithere', $factory->yieldContent('foo')); - } - - - public function testYieldSectionStopsAndYields() - { - $factory = $this->getFactory(); - $factory->startSection('foo'); - echo 'hi'; - $this->assertEquals('hi', $factory->yieldSection()); - } - - - public function testInjectStartsSectionWithContent() - { - $factory = $this->getFactory(); - $factory->inject('foo', 'hi'); - $this->assertEquals('hi', $factory->yieldContent('foo')); - } - - - public function testEmptyStringIsReturnedForNonSections() - { - $factory = $this->getFactory(); - $this->assertEquals('', $factory->yieldContent('foo')); - } - - - public function testSectionFlushing() - { - $factory = $this->getFactory(); - $factory->startSection('foo'); - echo 'hi'; - $factory->stopSection(); - - $this->assertCount(1, $factory->getSections()); - - $factory->flushSections(); - - $this->assertCount(0, $factory->getSections()); - } - - - public function testExceptionIsThrownForUnknownExtension() - { - $this->expectException('InvalidArgumentException'); - $factory = $this->getFactory(); - $factory->getFinder()->shouldReceive('find')->once()->with('view')->andReturn('view.foo'); - $factory->make('view'); - } - - - public function testExceptionsInSectionsAreThrown() - { - $engine = new CompilerEngine(m::mock(CompilerInterface::class)); - $engine->getCompiler()->shouldReceive('getCompiledPath')->andReturnUsing( - function ($path) { - return $path; - } - ); - $engine->getCompiler()->shouldReceive('isExpired')->twice()->andReturn(false); - $factory = $this->getFactory(); - $factory->getEngineResolver()->shouldReceive('resolve')->twice()->andReturn($engine); - $factory->getFinder()->shouldReceive('find')->once()->with('layout')->andReturn( - __DIR__ . '/fixtures/section-exception-layout.php' - ); - $factory->getFinder()->shouldReceive('find')->once()->with('view')->andReturn( - __DIR__ . '/fixtures/section-exception.php' - ); - $factory->getDispatcher()->shouldReceive('dispatch')->times(4); - - $this->expectException('Exception', 'section exception message'); - $factory->make('view')->render(); - } - - - protected function getFactory() - { - return new Factory( - m::mock(EngineResolver::class), - m::mock(ViewFinderInterface::class), - m::mock(Dispatcher::class) - ); - } - - - protected function getFactoryArgs() - { - return [ - m::mock(EngineResolver::class), - m::mock(ViewFinderInterface::class), - m::mock(Dispatcher::class), - ]; - } - -} diff --git a/tests/View/ViewFinderTest.php b/tests/View/ViewFinderTest.php deleted file mode 100755 index 8987a2214..000000000 --- a/tests/View/ViewFinderTest.php +++ /dev/null @@ -1,155 +0,0 @@ -getFinder(); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__ . '/foo.blade.php')->andReturn(true); - - $this->assertEquals(__DIR__.'/foo.blade.php', $finder->find('foo')); - } - - - public function testCascadingFileLoading() - { - $finder = $this->getFinder(); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__.'/foo.blade.php')->andReturn(false); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__.'/foo.php')->andReturn(true); - - $this->assertEquals(__DIR__.'/foo.php', $finder->find('foo')); - } - - - public function testDirectoryCascadingFileLoading() - { - $finder = $this->getFinder(); - $finder->addLocation(__DIR__.'/nested'); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__.'/foo.blade.php')->andReturn(false); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__.'/foo.php')->andReturn(false); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__.'/nested/foo.blade.php')->andReturn(true); - - $this->assertEquals(__DIR__.'/nested/foo.blade.php', $finder->find('foo')); - } - - - public function testNamespacedBasicFileLoading() - { - $finder = $this->getFinder(); - $finder->addNamespace('foo', __DIR__.'/foo'); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__.'/foo/bar/baz.blade.php')->andReturn(true); - - $this->assertEquals(__DIR__.'/foo/bar/baz.blade.php', $finder->find('foo::bar.baz')); - } - - - public function testCascadingNamespacedFileLoading() - { - $finder = $this->getFinder(); - $finder->addNamespace('foo', __DIR__.'/foo'); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__.'/foo/bar/baz.blade.php')->andReturn(false); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__.'/foo/bar/baz.php')->andReturn(true); - - $this->assertEquals(__DIR__.'/foo/bar/baz.php', $finder->find('foo::bar.baz')); - } - - - public function testDirectoryCascadingNamespacedFileLoading() - { - $finder = $this->getFinder(); - $finder->addNamespace('foo', [__DIR__.'/foo', __DIR__.'/bar']); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__.'/foo/bar/baz.blade.php')->andReturn(false); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__.'/foo/bar/baz.php')->andReturn(false); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__.'/bar/bar/baz.blade.php')->andReturn(true); - - $this->assertEquals(__DIR__.'/bar/bar/baz.blade.php', $finder->find('foo::bar.baz')); - } - - - public function testExceptionThrownWhenViewNotFound() - { - $this->expectException(InvalidArgumentException::class); - $finder = $this->getFinder(); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__ . '/foo.blade.php')->andReturn(false); - $finder->getFilesystem()->shouldReceive('exists')->once()->with(__DIR__ . '/foo.php')->andReturn(false); - - $finder->find('foo'); - } - - - public function testExceptionThrownOnInvalidViewName() - { - $this->expectException(InvalidArgumentException::class); - $finder = $this->getFinder(); - $finder->find('name::'); - } - - - public function testExceptionThrownWhenNoHintPathIsRegistered() - { - $this->expectException(InvalidArgumentException::class); - $finder = $this->getFinder(); - $finder->find('name::foo'); - } - - - public function testAddingExtensionPrependsNotAppends() - { - $finder = $this->getFinder(); - $finder->addExtension('baz'); - $extensions = $finder->getExtensions(); - $this->assertEquals('baz', reset($extensions)); - } - - - public function testAddingExtensionsReplacesOldOnes() - { - $finder = $this->getFinder(); - $finder->addExtension('baz'); - $finder->addExtension('baz'); - - $this->assertCount(3, $finder->getExtensions()); - } - - - public function testPassingViewWithHintReturnsTrue() - { - $finder = $this->getFinder(); - - $this->assertTrue($finder->hasHintInformation('hint::foo.bar')); - } - - - public function testPassingViewWithoutHintReturnsFalse() - { - $finder = $this->getFinder(); - - $this->assertFalse($finder->hasHintInformation('foo.bar')); - } - - - public function testPassingViewWithFalseHintReturnsFalse() - { - $finder = $this->getFinder(); - - $this->assertFalse($finder->hasHintInformation('::foo.bar')); - } - - - protected function getFinder() - { - return new Illuminate\View\FileViewFinder(m::mock(Filesystem::class), [__DIR__]); - } - -} diff --git a/tests/View/ViewPhpEngineTest.php b/tests/View/ViewPhpEngineTest.php deleted file mode 100755 index bdcccf7f3..000000000 --- a/tests/View/ViewPhpEngineTest.php +++ /dev/null @@ -1,22 +0,0 @@ -assertEquals("Hello World\n", $engine->get(__DIR__ . '/fixtures/basic.php')); - } - -} diff --git a/tests/View/ViewTest.php b/tests/View/ViewTest.php deleted file mode 100755 index b85d7ab38..000000000 --- a/tests/View/ViewTest.php +++ /dev/null @@ -1,232 +0,0 @@ -with('foo', 'bar'); - $view->with(['baz' => 'boom']); - $this->assertEquals(['foo' => 'bar', 'baz' => 'boom'], $view->getData()); - - - $view = new View(m::mock(Factory::class), m::mock( - EngineInterface::class - ), 'view', 'path', [] - ); - $view->withFoo('bar')->withBaz('boom'); - $this->assertEquals(['foo' => 'bar', 'baz' => 'boom'], $view->getData()); - } - - - public function testRenderProperlyRendersView() - { - $view = $this->getView(); - $view->getFactory()->shouldReceive('incrementRender')->once()->ordered(); - $view->getFactory()->shouldReceive('callComposer')->once()->ordered()->with($view); - $view->getFactory()->shouldReceive('getShared')->once()->andReturn(['shared' => 'foo']); - $view->getEngine()->shouldReceive('get')->once()->with('path', ['foo' => 'bar', 'shared' => 'foo'])->andReturn('contents'); - $view->getFactory()->shouldReceive('decrementRender')->once()->ordered(); - $view->getFactory()->shouldReceive('flushStateIfDoneRendering')->once(); - - $me = $this; - $callback = function(View $rendered, $contents) use ($me, $view) - { - $me->assertEquals($view, $rendered); - $me->assertEquals('contents', $contents); - }; - - $this->assertEquals('contents', $view->render($callback)); - } - - - public function testRenderSectionsReturnsEnvironmentSections() - { - $view = m::mock('Illuminate\View\View[render]', [ - m::mock(Factory::class), - m::mock(EngineInterface::class), - 'view', - 'path', - [], - ]); - - $view->shouldReceive('render')->with(m::type('Closure'))->once()->andReturn($sections = ['foo' => 'bar']); - - $this->assertEquals($sections, $view->renderSections()); - } - - - public function testSectionsAreNotFlushedWhenNotDoneRendering() - { - $view = $this->getView(); - $view->getFactory()->shouldReceive('incrementRender')->twice(); - $view->getFactory()->shouldReceive('callComposer')->twice()->with($view); - $view->getFactory()->shouldReceive('getShared')->twice()->andReturn(['shared' => 'foo']); - $view->getEngine()->shouldReceive('get')->twice()->with('path', ['foo' => 'bar', 'shared' => 'foo'])->andReturn('contents'); - $view->getFactory()->shouldReceive('decrementRender')->twice(); - $view->getFactory()->shouldReceive('flushStateIfDoneRendering')->twice(); - - $this->assertEquals('contents', $view->render()); - $this->assertEquals('contents', (string) $view); - } - - - public function testViewNestBindsASubView() - { - $view = $this->getView(); - $view->getFactory()->shouldReceive('make')->once()->with('foo', ['data']); - $result = $view->nest('key', 'foo', ['data']); - - $this->assertInstanceOf(View::class, $result); - } - - - public function testViewAcceptsArrayableImplementations() - { - $arrayable = m::mock(ArrayableInterface::class); - $arrayable->shouldReceive('toArray')->once()->andReturn(['foo' => 'bar', 'baz' => ['qux', 'corge']]); - - $view = new View( - m::mock(Factory::class), - m::mock(EngineInterface::class), - 'view', - 'path', - $arrayable - ); - - $this->assertEquals('bar', $view->foo); - $this->assertEquals(['qux', 'corge'], $view->baz); - } - - - public function testViewGettersSetters() - { - $view = $this->getView(); - $this->assertEquals($view->getName(), 'view'); - $this->assertEquals($view->getPath(), 'path'); - $data = $view->getData(); - $this->assertEquals($data['foo'], 'bar'); - $view->setPath('newPath'); - $this->assertEquals($view->getPath(), 'newPath'); - } - - - public function testViewArrayAccess() - { - $view = $this->getView(); - $this->assertInstanceOf('ArrayAccess', $view); - $this->assertTrue($view->offsetExists('foo')); - $this->assertEquals($view->offsetGet('foo'), 'bar'); - $view->offsetSet('foo','baz'); - $this->assertEquals($view->offsetGet('foo'), 'baz'); - $view->offsetUnset('foo'); - $this->assertFalse($view->offsetExists('foo')); - } - - - public function testViewMagicMethods() - { - $view = $this->getView(); - $this->assertTrue(isset($view->foo)); - $this->assertEquals($view->foo, 'bar'); - $view->foo = 'baz'; - $this->assertEquals($view->foo, 'baz'); - $this->assertEquals($view['foo'], $view->foo); - unset($view->foo); - $this->assertFalse(isset($view->foo)); - $this->assertFalse($view->offsetExists('foo')); - } - - - public function testViewBadMethod() - { - $this->expectException('BadMethodCallException'); - $view = $this->getView(); - $view->badMethodCall(); - } - - - public function testViewGatherDataWithRenderable() - { - $view = $this->getView(); - $view->getFactory()->shouldReceive('incrementRender')->once()->ordered(); - $view->getFactory()->shouldReceive('callComposer')->once()->ordered()->with($view); - $view->getFactory()->shouldReceive('getShared')->once()->andReturn(['shared' => 'foo']); - $view->getEngine()->shouldReceive('get')->once()->andReturn('contents'); - $view->getFactory()->shouldReceive('decrementRender')->once()->ordered(); - $view->getFactory()->shouldReceive('flushStateIfDoneRendering')->once(); - - $view->renderable = m::mock(Renderable::class); - $view->renderable->shouldReceive('render')->once()->andReturn('text'); - $this->assertEquals('contents', $view->render()); - } - - - public function testViewRenderSections() - { - $view = $this->getView(); - $view->getFactory()->shouldReceive('incrementRender')->once()->ordered(); - $view->getFactory()->shouldReceive('callComposer')->once()->ordered()->with($view); - $view->getFactory()->shouldReceive('getShared')->once()->andReturn(['shared' => 'foo']); - $view->getEngine()->shouldReceive('get')->once()->andReturn('contents'); - $view->getFactory()->shouldReceive('decrementRender')->once()->ordered(); - $view->getFactory()->shouldReceive('flushStateIfDoneRendering')->once(); - - $view->getFactory()->shouldReceive('getSections')->once()->andReturn(['foo','bar']); - $sections = $view->renderSections(); - $this->assertEquals($sections[0], 'foo'); - $this->assertEquals($sections[1], 'bar'); - } - - - public function testWithErrors() - { - $view = $this->getView(); - $errors = ['foo' => 'bar', 'qu' => 'ux']; - $this->assertSame($view, $view->withErrors($errors)); - $this->assertInstanceOf(MessageBag::class, $view->errors); - $foo = $view->errors->get('foo'); - $this->assertEquals($foo[0], 'bar'); - $qu = $view->errors->get('qu'); - $this->assertEquals($qu[0], 'ux'); - $data = ['foo' => 'baz']; - $this->assertSame($view, $view->withErrors(new MessageBag($data))); - $foo = $view->errors->get('foo'); - $this->assertEquals($foo[0], 'baz'); - } - - - protected function getView() - { - return new View( - m::mock(Factory::class), - m::mock(EngineInterface::class), - 'view', - 'path', - ['foo' => 'bar'] - ); - } - -} diff --git a/tests/View/fixtures/basic.php b/tests/View/fixtures/basic.php deleted file mode 100755 index 557db03de..000000000 --- a/tests/View/fixtures/basic.php +++ /dev/null @@ -1 +0,0 @@ -Hello World diff --git a/tests/View/fixtures/namespaced/basic.php b/tests/View/fixtures/namespaced/basic.php deleted file mode 100755 index 557db03de..000000000 --- a/tests/View/fixtures/namespaced/basic.php +++ /dev/null @@ -1 +0,0 @@ -Hello World diff --git a/tests/View/fixtures/nested/basic.php b/tests/View/fixtures/nested/basic.php deleted file mode 100755 index 557db03de..000000000 --- a/tests/View/fixtures/nested/basic.php +++ /dev/null @@ -1 +0,0 @@ -Hello World diff --git a/tests/View/fixtures/nested/child.php b/tests/View/fixtures/nested/child.php deleted file mode 100755 index ce0b1ebdb..000000000 --- a/tests/View/fixtures/nested/child.php +++ /dev/null @@ -1 +0,0 @@ -Hello World diff --git a/tests/View/fixtures/section-exception-layout.php b/tests/View/fixtures/section-exception-layout.php deleted file mode 100644 index 7b3acd8b8..000000000 --- a/tests/View/fixtures/section-exception-layout.php +++ /dev/null @@ -1 +0,0 @@ -yieldContent('content'); ?> diff --git a/tests/View/fixtures/section-exception.php b/tests/View/fixtures/section-exception.php deleted file mode 100644 index 13a8c901c..000000000 --- a/tests/View/fixtures/section-exception.php +++ /dev/null @@ -1,4 +0,0 @@ -make('layout', array_except(get_defined_vars(), ['__data', '__path']))->render(); ?> -startSection('content'); ?> - -stopSection(); ?>