diff --git a/actions/ConnectivityAction.php b/actions/ConnectivityAction.php index 9732d0aac05..e4e1e7c2724 100644 --- a/actions/ConnectivityAction.php +++ b/actions/ConnectivityAction.php @@ -14,9 +14,10 @@ class ConnectivityAction implements ActionInterface { private BridgeFactory $bridgeFactory; - public function __construct() - { - $this->bridgeFactory = new BridgeFactory(); + public function __construct( + BridgeFactory $bridgeFactory + ) { + $this->bridgeFactory = $bridgeFactory; } public function __invoke(Request $request): Response diff --git a/actions/DetectAction.php b/actions/DetectAction.php index cebbc307668..8d3d6263913 100644 --- a/actions/DetectAction.php +++ b/actions/DetectAction.php @@ -2,6 +2,14 @@ class DetectAction implements ActionInterface { + private BridgeFactory $bridgeFactory; + + public function __construct( + BridgeFactory $bridgeFactory + ) { + $this->bridgeFactory = $bridgeFactory; + } + public function __invoke(Request $request): Response { $url = $request->get('url'); @@ -14,14 +22,12 @@ public function __invoke(Request $request): Response return new Response(render(__DIR__ . '/../templates/error.html.php', ['message' => 'You must specify a format'])); } - $bridgeFactory = new BridgeFactory(); - - foreach ($bridgeFactory->getBridgeClassNames() as $bridgeClassName) { - if (!$bridgeFactory->isEnabled($bridgeClassName)) { + foreach ($this->bridgeFactory->getBridgeClassNames() as $bridgeClassName) { + if (!$this->bridgeFactory->isEnabled($bridgeClassName)) { continue; } - $bridge = $bridgeFactory->create($bridgeClassName); + $bridge = $this->bridgeFactory->create($bridgeClassName); $bridgeParams = $bridge->detectParameters($url); diff --git a/actions/DisplayAction.php b/actions/DisplayAction.php index 5265abd8e22..c00c0d5e649 100644 --- a/actions/DisplayAction.php +++ b/actions/DisplayAction.php @@ -4,11 +4,16 @@ class DisplayAction implements ActionInterface { private CacheInterface $cache; private Logger $logger; + private BridgeFactory $bridgeFactory; - public function __construct() - { - $this->cache = RssBridge::getCache(); - $this->logger = RssBridge::getLogger(); + public function __construct( + CacheInterface $cache, + Logger $logger, + BridgeFactory $bridgeFactory + ) { + $this->cache = $cache; + $this->logger = $logger; + $this->bridgeFactory = $bridgeFactory; } public function __invoke(Request $request): Response @@ -39,8 +44,7 @@ public function __invoke(Request $request): Response if (!$bridgeName) { return new Response(render(__DIR__ . '/../templates/error.html.php', ['message' => 'Missing bridge parameter']), 400); } - $bridgeFactory = new BridgeFactory(); - $bridgeClassName = $bridgeFactory->createBridgeClassName($bridgeName); + $bridgeClassName = $this->bridgeFactory->createBridgeClassName($bridgeName); if (!$bridgeClassName) { return new Response(render(__DIR__ . '/../templates/error.html.php', ['message' => 'Bridge not found']), 404); } @@ -48,7 +52,7 @@ public function __invoke(Request $request): Response if (!$format) { return new Response(render(__DIR__ . '/../templates/error.html.php', ['message' => 'You must specify a format']), 400); } - if (!$bridgeFactory->isEnabled($bridgeClassName)) { + if (!$this->bridgeFactory->isEnabled($bridgeClassName)) { return new Response(render(__DIR__ . '/../templates/error.html.php', ['message' => 'This bridge is not whitelisted']), 400); } @@ -62,7 +66,7 @@ public function __invoke(Request $request): Response define('NOPROXY', true); } - $bridge = $bridgeFactory->create($bridgeClassName); + $bridge = $this->bridgeFactory->create($bridgeClassName); $response = $this->createResponse($request, $bridge, $format); diff --git a/actions/FindfeedAction.php b/actions/FindfeedAction.php index 6654ca6d850..e18c3e1db55 100644 --- a/actions/FindfeedAction.php +++ b/actions/FindfeedAction.php @@ -7,6 +7,14 @@ */ class FindfeedAction implements ActionInterface { + private BridgeFactory $bridgeFactory; + + public function __construct( + BridgeFactory $bridgeFactory + ) { + $this->bridgeFactory = $bridgeFactory; + } + public function __invoke(Request $request): Response { $url = $request->get('url'); @@ -19,15 +27,13 @@ public function __invoke(Request $request): Response return new Response('You must specify a format', 400); } - $bridgeFactory = new BridgeFactory(); - $results = []; - foreach ($bridgeFactory->getBridgeClassNames() as $bridgeClassName) { - if (!$bridgeFactory->isEnabled($bridgeClassName)) { + foreach ($this->bridgeFactory->getBridgeClassNames() as $bridgeClassName) { + if (!$this->bridgeFactory->isEnabled($bridgeClassName)) { continue; } - $bridge = $bridgeFactory->create($bridgeClassName); + $bridge = $this->bridgeFactory->create($bridgeClassName); $bridgeParams = $bridge->detectParameters($url); diff --git a/actions/FrontpageAction.php b/actions/FrontpageAction.php index 6ab18d29782..824441b242b 100644 --- a/actions/FrontpageAction.php +++ b/actions/FrontpageAction.php @@ -2,6 +2,14 @@ final class FrontpageAction implements ActionInterface { + private BridgeFactory $bridgeFactory; + + public function __construct( + BridgeFactory $bridgeFactory + ) { + $this->bridgeFactory = $bridgeFactory; + } + public function __invoke(Request $request): Response { $token = $request->attribute('token'); @@ -9,10 +17,9 @@ public function __invoke(Request $request): Response $messages = []; $activeBridges = 0; - $bridgeFactory = new BridgeFactory(); - $bridgeClassNames = $bridgeFactory->getBridgeClassNames(); + $bridgeClassNames = $this->bridgeFactory->getBridgeClassNames(); - foreach ($bridgeFactory->getMissingEnabledBridges() as $missingEnabledBridge) { + foreach ($this->bridgeFactory->getMissingEnabledBridges() as $missingEnabledBridge) { $messages[] = [ 'body' => sprintf('Warning : Bridge "%s" not found', $missingEnabledBridge), 'level' => 'warning' @@ -21,8 +28,8 @@ public function __invoke(Request $request): Response $body = ''; foreach ($bridgeClassNames as $bridgeClassName) { - if ($bridgeFactory->isEnabled($bridgeClassName)) { - $body .= BridgeCard::render($bridgeClassName, $token); + if ($this->bridgeFactory->isEnabled($bridgeClassName)) { + $body .= BridgeCard::render($this->bridgeFactory, $bridgeClassName, $token); $activeBridges++; } } diff --git a/actions/ListAction.php b/actions/ListAction.php index 3dd8f4416e7..f6347f9c457 100644 --- a/actions/ListAction.php +++ b/actions/ListAction.php @@ -2,19 +2,25 @@ class ListAction implements ActionInterface { + private BridgeFactory $bridgeFactory; + + public function __construct( + BridgeFactory $bridgeFactory + ) { + $this->bridgeFactory = $bridgeFactory; + } + public function __invoke(Request $request): Response { $list = new \stdClass(); $list->bridges = []; $list->total = 0; - $bridgeFactory = new BridgeFactory(); - - foreach ($bridgeFactory->getBridgeClassNames() as $bridgeClassName) { - $bridge = $bridgeFactory->create($bridgeClassName); + foreach ($this->bridgeFactory->getBridgeClassNames() as $bridgeClassName) { + $bridge = $this->bridgeFactory->create($bridgeClassName); $list->bridges[$bridgeClassName] = [ - 'status' => $bridgeFactory->isEnabled($bridgeClassName) ? 'active' : 'inactive', + 'status' => $this->bridgeFactory->isEnabled($bridgeClassName) ? 'active' : 'inactive', 'uri' => $bridge->getURI(), 'donationUri' => $bridge->getDonationURI(), 'name' => $bridge->getName(), diff --git a/bin/cache-clear b/bin/cache-clear index 635f41d59c5..7146636035d 100755 --- a/bin/cache-clear +++ b/bin/cache-clear @@ -17,11 +17,8 @@ if (file_exists(__DIR__ . '/../config.ini.php')) { } Configuration::loadConfiguration($config, getenv()); -$logger = new SimpleLogger('rssbridge'); +$container = require __DIR__ . '/../lib/dependencies.php'; -$logger->addHandler(new StreamHandler('php://stderr', Logger::INFO)); - -$cacheFactory = new CacheFactory($logger); -$cache = $cacheFactory->create(); +$cache = $container['cache']; $cache->clear(); diff --git a/bin/cache-prune b/bin/cache-prune index 281c019df2b..37696e14637 100755 --- a/bin/cache-prune +++ b/bin/cache-prune @@ -17,11 +17,8 @@ if (file_exists(__DIR__ . '/../config.ini.php')) { } Configuration::loadConfiguration($config, getenv()); -$logger = new SimpleLogger('rssbridge'); +$container = require __DIR__ . '/../lib/dependencies.php'; -$logger->addHandler(new StreamHandler('php://stderr', Logger::INFO)); - -$cacheFactory = new CacheFactory($logger); -$cache = $cacheFactory->create(); +$cache = $container['cache']; $cache->prune(); diff --git a/bin/test b/bin/test new file mode 100755 index 00000000000..f3556fc1fb1 --- /dev/null +++ b/bin/test @@ -0,0 +1,29 @@ +#!/usr/bin/env php +debug('This is a test debug message'); + +$logger->info('This is a test info message'); + +$logger->error('This is a test error message'); diff --git a/bridges/TwitchBridge.php b/bridges/TwitchBridge.php index 424cd6e3b20..c273aaca0de 100644 --- a/bridges/TwitchBridge.php +++ b/bridges/TwitchBridge.php @@ -99,7 +99,7 @@ public function collectData() $user = $data->user; if ($user->videos === null) { // twitch regularly does this for unknown reasons - //$this->logger->info('Twitch returned empty set of videos', ['data' => $data]); + $this->debug->info('Twitch returned empty set of videos', ['data' => $data]); return; } diff --git a/index.php b/index.php index 2a61336311e..7b44194493b 100644 --- a/index.php +++ b/index.php @@ -17,7 +17,9 @@ } Configuration::loadConfiguration($config, getenv()); -$logger = new SimpleLogger('rssbridge'); +$container = require __DIR__ . '/lib/dependencies.php'; + +$logger = $container['logger']; set_exception_handler(function (\Throwable $e) use ($logger) { $response = new Response(render(__DIR__ . '/templates/exception.html.php', ['e' => $e]), 500); @@ -60,23 +62,6 @@ } }); -$cacheFactory = new CacheFactory($logger); - -// Uncomment this for info logging to fs -// $logger->addHandler(new StreamHandler('/tmp/rss-bridge.txt', Logger::INFO)); - -// Uncomment this for debug logging to fs -// $logger->addHandler(new StreamHandler('/tmp/rss-bridge-debug.txt', Logger::DEBUG)); - -if (Debug::isEnabled()) { - $logger->addHandler(new ErrorLogHandler(Logger::DEBUG)); - $cache = $cacheFactory->create('array'); -} else { - $logger->addHandler(new ErrorLogHandler(Logger::INFO)); - $cache = $cacheFactory->create(); -} -$httpClient = new CurlHttpClient(); - date_default_timezone_set(Configuration::getConfig('system', 'timezone')); $argv = $argv ?? null; @@ -88,7 +73,7 @@ } try { - $rssBridge = new RssBridge($logger, $cache, $httpClient); + $rssBridge = new RssBridge($container); $response = $rssBridge->main($request); $response->send(); } catch (\Throwable $e) { diff --git a/lib/BridgeCard.php b/lib/BridgeCard.php index f270c1a3672..855ddb9339a 100644 --- a/lib/BridgeCard.php +++ b/lib/BridgeCard.php @@ -2,10 +2,11 @@ final class BridgeCard { - public static function render(string $bridgeClassName, ?string $token): string - { - $bridgeFactory = new BridgeFactory(); - + public static function render( + BridgeFactory $bridgeFactory, + string $bridgeClassName, + ?string $token + ): string { $bridge = $bridgeFactory->create($bridgeClassName); $uri = $bridge->getURI(); diff --git a/lib/BridgeFactory.php b/lib/BridgeFactory.php index ad4332875de..c214e44b6fb 100644 --- a/lib/BridgeFactory.php +++ b/lib/BridgeFactory.php @@ -8,10 +8,12 @@ final class BridgeFactory private array $enabledBridges = []; private array $missingEnabledBridges = []; - public function __construct() - { - $this->cache = RssBridge::getCache(); - $this->logger = RssBridge::getLogger(); + public function __construct( + CacheInterface $cache, + Logger $logger + ) { + $this->cache = $cache; + $this->logger = $logger; // Create all possible bridge class names from fs foreach (scandir(__DIR__ . '/../bridges/') as $file) { diff --git a/lib/CacheFactory.php b/lib/CacheFactory.php index 90aa21ba7be..47bbbf72bfc 100644 --- a/lib/CacheFactory.php +++ b/lib/CacheFactory.php @@ -14,10 +14,6 @@ public function __construct( public function create(string $name = null): CacheInterface { - $name ??= Configuration::getConfig('cache', 'type'); - if (!$name) { - throw new \Exception('No cache type configured'); - } $cacheNames = []; foreach (scandir(PATH_LIB_CACHES) as $file) { if (preg_match('/^([^.]+)Cache\.php$/U', $file, $m)) { diff --git a/lib/Container.php b/lib/Container.php new file mode 100644 index 00000000000..6dd0b6d32d0 --- /dev/null +++ b/lib/Container.php @@ -0,0 +1,33 @@ +values[$offset] = $value; + } + + #[ReturnTypeWillChange] public function offsetGet($offset) + { + if (!isset($this->values[$offset])) { + throw new \Exception(sprintf('Unknown container key: "%s"', $offset)); + } + if (!isset($this->resolved[$offset])) { + $this->resolved[$offset] = $this->values[$offset]($this); + } + return $this->resolved[$offset]; + } + + #[ReturnTypeWillChange] public function offsetExists($offset) + { + } + + public function offsetUnset($offset): void + { + } +} diff --git a/lib/RssBridge.php b/lib/RssBridge.php index 35318c5ba57..9c8f5767229 100644 --- a/lib/RssBridge.php +++ b/lib/RssBridge.php @@ -2,18 +2,12 @@ final class RssBridge { - private static Logger $logger; - private static CacheInterface $cache; - private static HttpClient $httpClient; + private static Container $container; public function __construct( - Logger $logger, - CacheInterface $cache, - HttpClient $httpClient + Container $container ) { - self::$logger = $logger; - self::$cache = $cache; - self::$httpClient = $httpClient; + self::$container = $container; } public function main(Request $request): Response @@ -83,10 +77,9 @@ public function main(Request $request): Response return new Response(render(__DIR__ . '/../templates/error.html.php', ['message' => 'Invalid action']), 400); } - $className = '\\' . $actionName; - $actionObject = new $className(); + $controller = self::$container[$actionName]; - $response = $actionObject($request); + $response = $controller($request); return $response; } @@ -94,16 +87,16 @@ public function main(Request $request): Response public static function getLogger(): Logger { // null logger is only for the tests not to fail - return self::$logger ?? new NullLogger(); + return self::$container['logger'] ?? new NullLogger(); } public static function getCache(): CacheInterface { - return self::$cache; + return self::$container['cache']; } public static function getHttpClient(): HttpClient { - return self::$httpClient; + return self::$container['http_client']; } } diff --git a/lib/dependencies.php b/lib/dependencies.php new file mode 100644 index 00000000000..227a66f1b51 --- /dev/null +++ b/lib/dependencies.php @@ -0,0 +1,78 @@ +addHandler(new ErrorLogHandler(Logger::DEBUG)); + } else { + $logger->addHandler(new ErrorLogHandler(Logger::INFO)); + } + // Uncomment this for info logging to fs + // $logger->addHandler(new StreamHandler('/tmp/rss-bridge.txt', Logger::INFO)); + + // Uncomment this for debug logging to fs + //$logger->addHandler(new StreamHandler('/tmp/rss-bridge-debug.txt', Logger::DEBUG)); + return $logger; +}; + +$container['cache'] = function ($c) { + /** @var CacheFactory $cacheFactory */ + $cacheFactory = $c['cache_factory']; + $type = Configuration::getConfig('cache', 'type'); + if (!$type) { + throw new \Exception('No cache type configured'); + } + if (Debug::isEnabled()) { + $cache = $cacheFactory->create('array'); + } else { + $cache = $cacheFactory->create($type); + } + return $cache; +}; + +return $container; diff --git a/lib/logger.php b/lib/logger.php index 3ebe3b0afb9..74a0e713963 100644 --- a/lib/logger.php +++ b/lib/logger.php @@ -175,8 +175,9 @@ public function __invoke(array $record) $context = Json::encode($record['context']); } } + // Intentionally omitting newline $text = sprintf( - "[%s] %s.%s %s %s\n", + '[%s] %s.%s %s %s', $record['created_at']->format('Y-m-d H:i:s'), $record['name'], $record['level_name'],