2013-08-11 15:30:41 +04:00
|
|
|
<?php
|
2018-11-13 22:26:56 +03:00
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
final class BridgeFactory {
|
2016-09-10 21:41:11 +03:00
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
private $folder;
|
|
|
|
private $bridgeNames = [];
|
|
|
|
private $whitelist = [];
|
2016-09-10 21:41:11 +03:00
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
public function __construct(string $folder = PATH_LIB_BRIDGES)
|
|
|
|
{
|
|
|
|
$this->folder = $folder;
|
2016-09-10 21:41:11 +03:00
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
// create names
|
|
|
|
foreach(scandir($this->folder) as $file) {
|
|
|
|
if(preg_match('/^([^.]+)Bridge\.php$/U', $file, $m)) {
|
|
|
|
$this->bridgeNames[] = $m[1];
|
|
|
|
}
|
2016-09-10 21:41:11 +03:00
|
|
|
}
|
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
// create whitelist
|
|
|
|
if (file_exists(WHITELIST)) {
|
|
|
|
$contents = trim(file_get_contents(WHITELIST));
|
|
|
|
} elseif (file_exists(WHITELIST_DEFAULT)) {
|
|
|
|
$contents = trim(file_get_contents(WHITELIST_DEFAULT));
|
|
|
|
} else {
|
|
|
|
$contents = '';
|
2016-09-10 21:41:11 +03:00
|
|
|
}
|
2022-05-08 04:58:42 +03:00
|
|
|
if ($contents === '*') { // Whitelist all bridges
|
|
|
|
$this->whitelist = $this->getBridgeNames();
|
|
|
|
} else {
|
|
|
|
foreach (explode("\n", $contents) as $bridgeName) {
|
|
|
|
$this->whitelist[] = $this->sanitizeBridgeName($bridgeName);
|
2016-09-10 21:41:11 +03:00
|
|
|
}
|
|
|
|
}
|
2018-11-11 00:26:56 +03:00
|
|
|
}
|
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
public function create(string $name): BridgeInterface
|
|
|
|
{
|
|
|
|
if(preg_match('/^[A-Z][a-zA-Z0-9-]*$/', $name)) {
|
|
|
|
$className = sprintf('%sBridge', $this->sanitizeBridgeName($name));
|
|
|
|
return new $className();
|
2018-11-11 00:26:56 +03:00
|
|
|
}
|
2022-05-08 04:58:42 +03:00
|
|
|
throw new \InvalidArgumentException('Bridge name invalid!');
|
2018-11-11 00:26:56 +03:00
|
|
|
}
|
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
public function getBridgeNames(): array
|
|
|
|
{
|
|
|
|
return $this->bridgeNames;
|
2018-11-11 00:26:56 +03:00
|
|
|
}
|
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
public function isWhitelisted($name): bool
|
|
|
|
{
|
|
|
|
return in_array($this->sanitizeBridgeName($name), $this->whitelist);
|
|
|
|
}
|
2018-11-11 00:26:56 +03:00
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
private function sanitizeBridgeName($name) {
|
2018-11-11 00:26:56 +03:00
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
if(!is_string($name)) {
|
|
|
|
return null;
|
|
|
|
}
|
2019-06-06 21:59:29 +03:00
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
// Trim trailing '.php' if exists
|
|
|
|
if (preg_match('/(.+)(?:\.php)/', $name, $matches)) {
|
|
|
|
$name = $matches[1];
|
|
|
|
}
|
2018-11-11 00:26:56 +03:00
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
// Trim trailing 'Bridge' if exists
|
|
|
|
if (preg_match('/(.+)(?:Bridge)/i', $name, $matches)) {
|
|
|
|
$name = $matches[1];
|
|
|
|
}
|
2018-11-11 00:26:56 +03:00
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
// Improve performance for correctly written bridge names
|
|
|
|
if (in_array($name, $this->getBridgeNames())) {
|
|
|
|
$index = array_search($name, $this->getBridgeNames());
|
|
|
|
return $this->getBridgeNames()[$index];
|
2018-11-11 00:26:56 +03:00
|
|
|
}
|
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
// The name is valid if a corresponding bridge file is found on disk
|
|
|
|
if (in_array(strtolower($name), array_map('strtolower', $this->getBridgeNames()))) {
|
|
|
|
$index = array_search(strtolower($name), array_map('strtolower', $this->getBridgeNames()));
|
|
|
|
return $this->getBridgeNames()[$index];
|
|
|
|
}
|
2018-11-11 00:26:56 +03:00
|
|
|
|
2022-05-08 04:58:42 +03:00
|
|
|
Debug::log('Invalid bridge name specified: "' . $name . '"!');
|
|
|
|
return null;
|
2016-09-10 21:41:11 +03:00
|
|
|
}
|
2016-08-24 21:48:12 +03:00
|
|
|
}
|