Last active
April 17, 2020 08:10
-
-
Save Chemaclass/01d3f42685ff69f6897192202a32014d to your computer and use it in GitHub Desktop.
This is the code that I used to verify locally my answer for a concret stackoverflow question
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php declare(strict_types=1); | |
| # https://stackoverflow.com/a/61230034/3454593 | |
| // Usage example: | |
| $cacheManager = new CachedRemoteSiteManager( | |
| new class implements CacheNormalizer { | |
| public function normalize(string $text): string { | |
| return substr($text, 17, 2); | |
| } | |
| }, | |
| new class implements PlanDomainToCache { | |
| public function buildUrl(Plan $plan): string { | |
| return "https://remotedomain.com/?get=price&product={$plan->product()}¤cy={$plan->currency()}"; | |
| } | |
| }, | |
| new class implements CachePersistence { | |
| public function shouldCreateOrUpdate(string $path): bool { | |
| return !\file_exists($path) || \time() - \filemtime($path) > 1600; | |
| } | |
| public function getContent(string $path): string { | |
| return \file_get_contents($path); | |
| } | |
| public function write(string $path, string $content): void { | |
| \file_put_contents($path, $content); | |
| } | |
| } | |
| ); | |
| $plan = new Plan('cache.dir', $productA = 10, $EUR = 2); | |
| $cacheManager->updateIfNecessary($plan); | |
| // The code: | |
| interface CacheNormalizer { | |
| public function normalize(string $text): string; | |
| } | |
| interface CachePersistence { | |
| public function shouldCreateOrUpdate(string $path): bool; | |
| public function getContent(string $path): string; | |
| public function write(string $path, string $content): void; | |
| } | |
| interface PlanDomainToCache { | |
| public function buildUrl(Plan $plan): string; | |
| } | |
| final class CachedRemoteSiteManager { | |
| private CacheNormalizer $normalizer; | |
| private PlanDomainToCache $planDomainToCache; | |
| private CachePersistence $persistence; | |
| public function __construct(CacheNormalizer $normalizer, PlanDomainToCache $toCache, CachePersistence $persistence) { | |
| $this->normalizer = $normalizer; | |
| $this->planDomainToCache = $toCache; | |
| $this->persistence = $persistence; | |
| } | |
| public function updateIfNecessary(Plan $plan): void { | |
| if ($this->persistence->shouldCreateOrUpdate($plan->cacheDirectory())) { | |
| $this->createOrUpdateCache($plan); | |
| } | |
| } | |
| private function createOrUpdateCache(Plan $plan): void { | |
| $urlToCache = $this->planDomainToCache->buildUrl($plan); | |
| $textToCache = $this->persistence->getContent($urlToCache); | |
| $this->persistence->write($plan->cacheDirectory(), $this->normalizer->normalize($textToCache)); | |
| } | |
| } | |
| final class Plan { | |
| private string $cacheDirectory; | |
| private int $product; | |
| private int $currency; | |
| public function __construct(string $cacheDir, int $product, int $currency) | |
| { | |
| $this->cacheDirectory = $cacheDir; | |
| $this->product = $product; | |
| $this->currency = $currency; | |
| } | |
| public function cacheDirectory(): string { | |
| return $this->cacheDirectory; | |
| } | |
| public function product(): int { | |
| return $this->product; | |
| } | |
| public function currency(): int { | |
| return $this->currency; | |
| } | |
| public function __toString(): string { | |
| return "Plan d:{$this->cacheDirectory},c:{$this->currency},p:{$this->product}"; | |
| } | |
| } | |
| // The tests: | |
| use PHPUnit\Framework\TestCase; | |
| final class CachedRemoteSiteManagerTest extends TestCase | |
| { | |
| public function testCacheShouldNotBeCreated(): void { | |
| $persistence = $this->stubCachePersistence($shouldCreateOrUpdate = false); | |
| $cacheManager = new CachedRemoteSiteManager($this->newNormalizer(), $this->newPlanDomainToCache(), $persistence); | |
| $cacheManager->updateIfNecessary(new Plan('cache.dir', $productA = 10, $EUR = 2)); | |
| self::assertEmpty($persistence->memoryList()); | |
| } | |
| public function testCacheShouldBeCreated(): void { | |
| $persistence = $this->stubCachePersistence($shouldCreateOrUpdate = true); | |
| $cacheManager = new CachedRemoteSiteManager($this->newNormalizer(), $this->newPlanDomainToCache(), $persistence); | |
| $plan = new Plan('cache.dir', $productA = 10, $EUR = 2); | |
| $cacheManager->updateIfNecessary($plan); | |
| self::assertEquals(['cache.dir' => (string) $plan], $persistence->memoryList()); | |
| } | |
| private function newNormalizer(): CacheNormalizer { | |
| return new class implements CacheNormalizer { | |
| public function normalize(string $text): string { | |
| return $text; | |
| } | |
| }; | |
| } | |
| private function newPlanDomainToCache(): PlanDomainToCache { | |
| return new class implements PlanDomainToCache { | |
| public function buildUrl(Plan $plan): string { | |
| return (string) $plan; | |
| } | |
| }; | |
| } | |
| private function stubCachePersistence(bool $shouldCreateOrUpdate): CachePersistence { | |
| return new class ($shouldCreateOrUpdate) implements CachePersistence { | |
| private array $memoryList = []; | |
| private bool $shouldCreateOrUpdate; | |
| public function __construct(bool $shouldCreateOrUpdate) { | |
| $this->shouldCreateOrUpdate = $shouldCreateOrUpdate; | |
| } | |
| public function shouldCreateOrUpdate(string $path): bool { | |
| return $this->shouldCreateOrUpdate; | |
| } | |
| public function getContent(string $path): string { | |
| return $path; | |
| } | |
| public function write(string $path, string $content): void { | |
| $this->memoryList[$path] = $content; | |
| } | |
| public function memoryList(): array { | |
| return $this->memoryList; | |
| } | |
| }; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment