$part !== '' && $part !== '.' ) ); for ($i = count($parts), $probes = 0; $i >= 0 && $probes <= self::MAX_UP_LEVELS; $i--, $probes++) { $home = implode('/', array_slice($parts, 0, $i)); $registryFile = ($home === '' ? '' : $home . '/') . self::REGISTRY_FILE; try { if (!$fs->fileExists($registryFile)) { continue; } // The nearest home directory above the inspected one owns it, so its // registry is the only one that can describe it: stop here either way. return $this->matchRegisteredApp($fs, $registryFile, $path, array_slice($parts, $i)); } catch (FilesystemException) { // skip dir if it is inaccessible return new EmptyMatchResult(); } } return new EmptyMatchResult(); } /** * @param string[] $relativeParts Inspected path, relative to the home directory * @throws FilesystemException */ private function matchRegisteredApp( Filesystem $fs, string $registryFile, string $path, array $relativeParts ): MatchResultInterface { // The home directory itself is not an application, only a host for them. if ($relativeParts === []) { return new EmptyMatchResult(); } try { $registry = json_decode($fs->read($registryFile), true, 512, JSON_THROW_ON_ERROR); } catch (JsonException) { // ignore registry.json errors return new EmptyMatchResult(); } if (!is_array($registry) || !is_array($registry['apps'] ?? null)) { return new EmptyMatchResult(); } $relative = implode('/', $relativeParts); foreach ($registry['apps'] as $app) { if (is_array($app) && $this->appDir($app) === $relative) { return new MatchResult($path, null, $this->stringValue($app, 'name')); } } return new EmptyMatchResult(); } /** * The one home-relative directory that identifies the application. A record that * names the container it was deployed into is deployed; one that does not is still * staged. */ private function appDir(array $app): ?string { if (($container = $this->stringValue($app, '_container_name')) !== null) { return sprintf(self::DEPLOYED_DIR, $container); } if (($name = $this->stringValue($app, 'name')) !== null) { return sprintf(self::STAGED_DIR, $name); } return null; } private function stringValue(array $app, string $key): ?string { $value = $app[$key] ?? null; return is_string($value) && $value !== '' ? $value : null; } }