useCache()) { return; } $models = $this->getModels(); $map = $this->getModelMap($models); $this->mapModels($map); } /** * @return string */ public function getCachePath(): string { return base_path('bootstrap/cache/morphmap.php'); } /** * @return string */ public function getPackageBasePath(): string { return base_path('vendor/wm/'); } /** * @return array */ public function getModels(): array { $paths = $this->getModelPaths(); if (count($paths) === 0) { return []; } return $this->scan($paths); } /** * @param array $models * * @return array */ public function getModelMap(array $models): array { $map = []; foreach ($models as $modelName => $namespace) { Arr::set($map, $this->getModelAlias($modelName), $namespace); } return $map; } /** * @return bool */ private function useCache(): bool { if (!file_exists($cache = $this->getCachePath())) { return false; } $this->mapModels(include $cache); return true; } /** * @return array */ private function getModelPaths(): array { $vendorDirectory = $this->getPackageBasePath(); $scannedDirectory = array_diff(scandir($vendorDirectory), array('..', '.')); $dirs = []; foreach ($scannedDirectory as $dir) { $dirs[$dir] = $vendorDirectory . $dir . '/src/Models'; } return $dirs; } /** * @param array $paths * * @return array */ private function scan(array $paths): array { $models = []; foreach ($paths as $moduleName => $path) { if (!is_dir($path)) { continue; } $modelFiles = array_diff(scandir($path), array('..', '.')); foreach ($modelFiles as $modelFileName) { if (!is_file($path . DIRECTORY_SEPARATOR . $modelFileName)) { continue; } $modelNamespace = 'WM\\' . Str::studly($moduleName) . '\\Models\\' . basename($modelFileName, '.php'); if ($this->isModel($modelNamespace)) { $models[basename($modelFileName, '.php')] = $modelNamespace; } } } return $models; } /** * @param array $map * * @return bool */ private function isModel($namespace) { if (!class_exists($namespace)) { return false; } $reflection = new ReflectionClass($namespace); if ($reflection->isAbstract() || !is_subclass_of($namespace, Model::class)) { return false; } return true; } /** * @param array $map * * @return void */ private function mapModels(array $map): void { $existing = Relation::morphMap() ?: []; if (count($existing) > 0) { $map = collect($map) ->reject(function (string $class, string $alias) use ($existing): bool { return array_key_exists($alias, $existing) || in_array($class, $existing, true); }) ->toArray(); } Relation::morphMap($map); } /** * @param string $model * * @return string */ private function getModelAlias(string $model): string { $callback = ''; if ($callback && is_callable($callback)) { return $callback($model); } return $this->getModelName($model); } /** * @param string $model * * @return string */ private function getModelName(string $model): string { return Str::snake($model); } }