Initial commit
This commit is contained in:
commit
d673f56c82
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/vendor/
|
||||
/.idea/
|
||||
/var/doc/*
|
||||
/var/cache/*
|
31
bin/app.php
Normal file
31
bin/app.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Domain\Model\ASRockMemoryQVL;
|
||||
use Domain\Model\MemoryConfiguration;
|
||||
use Domain\Normalizer\Decorator\PricewatchDecorator;
|
||||
use Domain\Normalizer\MemoryConfigurationNormalizer;
|
||||
use Encoder\EncoderFactory;
|
||||
use IO\Downloader;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
// setup
|
||||
$list = new ASRockMemoryQVL('AMD', 'X570 Pro4', cpuFamily: 'MS');
|
||||
$downloader = new Downloader();
|
||||
$scraper = new MemoryQVLScraper();
|
||||
|
||||
// scrape and filter
|
||||
$page = $downloader->download($list);
|
||||
$configurations = $scraper->scrape($page);
|
||||
$selection = $configurations->filter(fn(MemoryConfiguration $memory) => in_array($memory->numberOfModules, [2, 4])
|
||||
&& $memory->totalSize >= 16
|
||||
&& $memory->speed >= 3600
|
||||
&& $memory->overclockingVerified
|
||||
);
|
||||
|
||||
// data presentation
|
||||
$normalizer = new MemoryConfigurationNormalizer();
|
||||
$normalizer = PricewatchDecorator::decorate($normalizer);
|
||||
$encoderFactory = new EncoderFactory($normalizer);
|
||||
$encoder = $encoderFactory->getEncoder($argv[1] ?? 'csv');
|
||||
print($encoder->encode($selection));
|
31
composer.json
Normal file
31
composer.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "vendor_name/asrock-memory-listing",
|
||||
"description": "description",
|
||||
"minimum-stability": "stable",
|
||||
"license": "proprietary",
|
||||
"authors": [
|
||||
{
|
||||
"name": "joop",
|
||||
"email": "email@example.com"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "^8.0"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"": ["src"]
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/var-dumper": "^5.2"
|
||||
},
|
||||
"require": {
|
||||
"symfony/dom-crawler": "^5.2",
|
||||
"symfony/css-selector": "^5.2",
|
||||
"ext-curl": "*",
|
||||
"illuminate/collections": "^8.38"
|
||||
}
|
||||
}
|
737
composer.lock
generated
Normal file
737
composer.lock
generated
Normal file
@ -0,0 +1,737 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "26034160d32c56d1d1d217b4cc155139",
|
||||
"packages": [
|
||||
{
|
||||
"name": "illuminate/collections",
|
||||
"version": "v8.38.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/collections.git",
|
||||
"reference": "21690cd5591f2d42d792e5e4a687f9beba829f1d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/collections/zipball/21690cd5591f2d42d792e5e4a687f9beba829f1d",
|
||||
"reference": "21690cd5591f2d42d792e5e4a687f9beba829f1d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/contracts": "^8.0",
|
||||
"illuminate/macroable": "^8.0",
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/var-dumper": "Required to use the dump method (^5.1.4)."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Support\\": ""
|
||||
},
|
||||
"files": [
|
||||
"helpers.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Collections package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2021-04-14T11:48:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/contracts",
|
||||
"version": "v8.38.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/contracts.git",
|
||||
"reference": "5764f703ea8f74ced163125d810951cd5ef2b7e1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/contracts/zipball/5764f703ea8f74ced163125d810951cd5ef2b7e1",
|
||||
"reference": "5764f703ea8f74ced163125d810951cd5ef2b7e1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"psr/container": "^1.0",
|
||||
"psr/simple-cache": "^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Contracts\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Contracts package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2021-04-01T13:09:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "illuminate/macroable",
|
||||
"version": "v8.38.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/illuminate/macroable.git",
|
||||
"reference": "300aa13c086f25116b5f3cde3ca54ff5c822fb05"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/illuminate/macroable/zipball/300aa13c086f25116b5f3cde3ca54ff5c822fb05",
|
||||
"reference": "300aa13c086f25116b5f3cde3ca54ff5c822fb05",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Illuminate\\Support\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "The Illuminate Macroable package.",
|
||||
"homepage": "https://laravel.com",
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2020-10-27T15:20:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
"version": "1.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/container.git",
|
||||
"reference": "8622567409010282b7aeebe4bb841fe98b58dcaf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf",
|
||||
"reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Container\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common Container Interface (PHP FIG PSR-11)",
|
||||
"homepage": "https://github.com/php-fig/container",
|
||||
"keywords": [
|
||||
"PSR-11",
|
||||
"container",
|
||||
"container-interface",
|
||||
"container-interop",
|
||||
"psr"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-fig/container/issues",
|
||||
"source": "https://github.com/php-fig/container/tree/1.1.1"
|
||||
},
|
||||
"time": "2021-03-05T17:36:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/simple-cache",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/simple-cache.git",
|
||||
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
|
||||
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\SimpleCache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interfaces for simple caching",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"caching",
|
||||
"psr",
|
||||
"psr-16",
|
||||
"simple-cache"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/simple-cache/tree/master"
|
||||
},
|
||||
"time": "2017-10-23T01:57:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
"version": "v5.2.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/css-selector.git",
|
||||
"reference": "f65f217b3314504a1ec99c2d6ef69016bb13490f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/f65f217b3314504a1ec99c2d6ef69016bb13490f",
|
||||
"reference": "f65f217b3314504a1ec99c2d6ef69016bb13490f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\CssSelector\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Jean-François Simon",
|
||||
"email": "jeanfrancois.simon@sensiolabs.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Converts CSS selectors to XPath expressions",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/css-selector/tree/v5.2.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-01-27T10:01:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/dom-crawler",
|
||||
"version": "v5.2.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/dom-crawler.git",
|
||||
"reference": "400e265163f65aceee7e904ef532e15228de674b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/400e265163f65aceee7e904ef532e15228de674b",
|
||||
"reference": "400e265163f65aceee7e904ef532e15228de674b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/polyfill-ctype": "~1.8",
|
||||
"symfony/polyfill-mbstring": "~1.0",
|
||||
"symfony/polyfill-php80": "^1.15"
|
||||
},
|
||||
"conflict": {
|
||||
"masterminds/html5": "<2.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"masterminds/html5": "^2.6",
|
||||
"symfony/css-selector": "^4.4|^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/css-selector": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\DomCrawler\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Eases DOM navigation for HTML and XML documents",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/dom-crawler/tree/v5.2.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-02-15T18:55:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.22.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "c6c942b1ac76c82448322025e084cadc56048b4e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e",
|
||||
"reference": "c6c942b1ac76c82448322025e084cadc56048b4e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ctype": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.22-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Ctype\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Gert de Pagter",
|
||||
"email": "BackEndTea@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for ctype functions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"ctype",
|
||||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-01-07T16:49:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.22.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "5232de97ee3b75b0360528dae24e73db49566ab1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1",
|
||||
"reference": "5232de97ee3b75b0360528dae24e73db49566ab1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.22-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Mbstring\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for the Mbstring extension",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"mbstring",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-01-22T09:19:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.22.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91",
|
||||
"reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.22-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Php80\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"classmap": [
|
||||
"Resources/stubs"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ion Bazan",
|
||||
"email": "ion.bazan@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-01-07T16:49:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-dumper",
|
||||
"version": "v5.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/var-dumper.git",
|
||||
"reference": "89412a68ea2e675b4e44f260a5666729f77f668e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/89412a68ea2e675b4e44f260a5666729f77f668e",
|
||||
"reference": "89412a68ea2e675b4e44f260a5666729f77f668e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/polyfill-mbstring": "~1.0",
|
||||
"symfony/polyfill-php80": "^1.15"
|
||||
},
|
||||
"conflict": {
|
||||
"phpunit/phpunit": "<5.4.3",
|
||||
"symfony/console": "<4.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-iconv": "*",
|
||||
"symfony/console": "^4.4|^5.0",
|
||||
"symfony/process": "^4.4|^5.0",
|
||||
"twig/twig": "^2.13|^3.0.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
|
||||
"ext-intl": "To show region name in time zone dump",
|
||||
"symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
|
||||
},
|
||||
"bin": [
|
||||
"Resources/bin/var-dump-server"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"Resources/functions/dump.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\VarDumper\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides mechanisms for walking through any arbitrary PHP variable",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"debug",
|
||||
"dump"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/var-dumper/tree/v5.2.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-03-28T09:42:18+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"ext-curl": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.0.0"
|
||||
}
|
28
src/Domain/Model/ASRockMemoryQVL.php
Normal file
28
src/Domain/Model/ASRockMemoryQVL.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Domain\Model;
|
||||
|
||||
use Stringable;
|
||||
|
||||
class ASRockMemoryQVL implements Stringable
|
||||
{
|
||||
private string $url;
|
||||
|
||||
public function __construct(
|
||||
string $cpuManufacturer,
|
||||
string $motherboard,
|
||||
string $cpuFamily
|
||||
)
|
||||
{
|
||||
$this->url = sprintf('https://www.asrock.com/mb/%s/%s/Memory-%s.asp',
|
||||
strtoupper(trim($cpuManufacturer)),
|
||||
rawurlencode(trim($motherboard)),
|
||||
strtoupper(trim($cpuFamily))
|
||||
);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
}
|
53
src/Domain/Model/MemoryConfiguration.php
Normal file
53
src/Domain/Model/MemoryConfiguration.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Domain\Model;
|
||||
|
||||
class MemoryConfiguration
|
||||
{
|
||||
public int $moduleSize;
|
||||
public int $totalSize;
|
||||
public string $totalSizeHr;
|
||||
public int $numberOfModules;
|
||||
public bool $overclockingVerified;
|
||||
public bool $dualChannelOverclockingVerified;
|
||||
|
||||
public function __construct(
|
||||
public string $type,
|
||||
public string $vendor,
|
||||
public int $speed,
|
||||
public int $supportedSpeed,
|
||||
public string $moduleSizeHr,
|
||||
public string $module,
|
||||
public string $chip,
|
||||
public bool $isDualSided,
|
||||
public string $dimmSocketSupport,
|
||||
public string $overclockingSupport,
|
||||
public string $note
|
||||
)
|
||||
{
|
||||
$this->moduleSize = filter_var($this->moduleSizeHr, FILTER_SANITIZE_NUMBER_INT);
|
||||
$this->overclockingVerified = in_array($this->overclockingSupport, ['v', '2'], true);
|
||||
$this->dualChannelOverclockingVerified = $this->overclockingSupport === '2';
|
||||
|
||||
$this->deriveAdditionalFields();
|
||||
}
|
||||
|
||||
private function deriveAdditionalFields(): void
|
||||
{
|
||||
$this->findTotalSize();
|
||||
$this->numberOfModules = $this->totalSize / $this->moduleSize;
|
||||
}
|
||||
|
||||
private function findTotalSize(): void
|
||||
{
|
||||
// Initially 8 times the module size
|
||||
$this->totalSize = 8 * $this->moduleSize;
|
||||
|
||||
// Work our way down to the module size...
|
||||
while (!str_contains($this->module, $this->totalSize) && $this->totalSize > $this->moduleSize) {
|
||||
$this->totalSize /= 2;
|
||||
}
|
||||
|
||||
$this->totalSizeHr = sprintf('%dGB', $this->totalSize);
|
||||
}
|
||||
}
|
34
src/Domain/Normalizer/Decorator/NormalizerDecorator.php
Normal file
34
src/Domain/Normalizer/Decorator/NormalizerDecorator.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Domain\Normalizer\Decorator;
|
||||
|
||||
use Domain\Normalizer\Normalizer;
|
||||
|
||||
abstract class NormalizerDecorator implements Normalizer
|
||||
{
|
||||
private function __construct(
|
||||
private Normalizer $parent
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public static function decorate(Normalizer $normalizer): static
|
||||
{
|
||||
return new static($normalizer);
|
||||
}
|
||||
|
||||
abstract protected function getAdditionalHeaders(): array;
|
||||
|
||||
abstract public function makePass(array $normalized): array;
|
||||
|
||||
final public function getHeaders(): array
|
||||
{
|
||||
return array_merge($this->parent->getHeaders(), $this->getAdditionalHeaders());
|
||||
}
|
||||
|
||||
final public function normalize(object $object): array
|
||||
{
|
||||
$normalized = $this->parent->normalize($object);
|
||||
return $this->makePass($normalized);
|
||||
}
|
||||
}
|
34
src/Domain/Normalizer/Decorator/PricewatchDecorator.php
Normal file
34
src/Domain/Normalizer/Decorator/PricewatchDecorator.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Domain\Normalizer\Decorator;
|
||||
|
||||
class PricewatchDecorator extends NormalizerDecorator
|
||||
{
|
||||
public function makePass(array $normalized): array
|
||||
{
|
||||
$module = $normalized['module'] ?? '-';
|
||||
$module = $this->selectSignificantTerms($module);
|
||||
|
||||
$normalized['pricewatch_url'] = sprintf(
|
||||
'https://tweakers.net/pricewatch/zoeken/?keyword=%s',
|
||||
rawurlencode($module)
|
||||
);
|
||||
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
protected function getAdditionalHeaders(): array
|
||||
{
|
||||
return ['pricewatch_url'];
|
||||
}
|
||||
|
||||
private function selectSignificantTerms(string $module): string
|
||||
{
|
||||
$parts = explode(' ', trim($module), 2);
|
||||
if ((count($parts) === 2) && stripos($parts[1], 'ver') !== false) {
|
||||
return $parts[0];
|
||||
}
|
||||
|
||||
return $module;
|
||||
}
|
||||
}
|
54
src/Domain/Normalizer/MemoryConfigurationNormalizer.php
Normal file
54
src/Domain/Normalizer/MemoryConfigurationNormalizer.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Domain\Normalizer;
|
||||
|
||||
use Domain\Model\MemoryConfiguration;
|
||||
|
||||
class MemoryConfigurationNormalizer implements Normalizer
|
||||
{
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getHeaders(): array
|
||||
{
|
||||
return [
|
||||
'vendor',
|
||||
'module',
|
||||
'type',
|
||||
'speed',
|
||||
'supported_speed',
|
||||
'number_of_modules',
|
||||
'module_size',
|
||||
'total_size',
|
||||
'chip',
|
||||
'dual_sided',
|
||||
'dimm_socket_support',
|
||||
'overclocking_support',
|
||||
'overclocking_verified',
|
||||
'dc_overclocking_verified',
|
||||
'note',
|
||||
];
|
||||
}
|
||||
|
||||
public function normalize(object $object): array
|
||||
{
|
||||
/** @var MemoryConfiguration $object */
|
||||
return [
|
||||
'vendor' => $object->vendor,
|
||||
'module' => $object->module,
|
||||
'type' => $object->type,
|
||||
'speed' => $object->speed,
|
||||
'supported_speed' => $object->supportedSpeed,
|
||||
'number_of_modules' => $object->numberOfModules,
|
||||
'module_size' => $object->moduleSizeHr,
|
||||
'total_size' => $object->totalSizeHr,
|
||||
'chip' => $object->chip,
|
||||
'dual_sided' => $object->isDualSided,
|
||||
'dimm_socket_support' => $object->dimmSocketSupport,
|
||||
'overclocking_support' => $object->overclockingSupport,
|
||||
'overclocking_verified' => $object->overclockingVerified,
|
||||
'dc_overclocking_verified' => $object->dualChannelOverclockingVerified,
|
||||
'note' => $object->note,
|
||||
];
|
||||
}
|
||||
}
|
13
src/Domain/Normalizer/Normalizer.php
Normal file
13
src/Domain/Normalizer/Normalizer.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Domain\Normalizer;
|
||||
|
||||
use Domain\Normalizer\Decorator\NormalizerDecorator;
|
||||
|
||||
interface Normalizer
|
||||
{
|
||||
public function getHeaders(): array;
|
||||
|
||||
public function normalize(object $object): array;
|
||||
|
||||
}
|
48
src/Encoder/CsvEncoder.php
Normal file
48
src/Encoder/CsvEncoder.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Encoder;
|
||||
|
||||
use Domain\Normalizer\Normalizer;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class CsvEncoder implements StringEncoder
|
||||
{
|
||||
public function __construct(
|
||||
private Normalizer $normalizer,
|
||||
private string $columnSeparator = ',',
|
||||
private string $rowSeparator = PHP_EOL,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function encode(Collection $items): string
|
||||
{
|
||||
$items = $items->values();
|
||||
$buffer = implode($this->columnSeparator, $this->normalizer->getHeaders());
|
||||
$buffer .= $this->rowSeparator;
|
||||
|
||||
$items->each(function (object $object) use (&$buffer) {
|
||||
$normalized = $this->normalizer->normalize($object);
|
||||
$buffer .= collect($normalized)
|
||||
->map([CsvEncoder::class, 'formatBoolean'])
|
||||
->map([CsvEncoder::class, 'formatEmpty'])
|
||||
->implode($this->columnSeparator);
|
||||
$buffer .= $this->rowSeparator;
|
||||
});
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
public static function formatBoolean(mixed $value): mixed
|
||||
{
|
||||
if (!is_bool($value)) {
|
||||
return $value;
|
||||
}
|
||||
return true === $value ? 'yes' : 'no';
|
||||
}
|
||||
|
||||
public static function formatEmpty(mixed $value): mixed
|
||||
{
|
||||
return empty($value) ? '-' : $value;
|
||||
}
|
||||
}
|
24
src/Encoder/EncoderFactory.php
Normal file
24
src/Encoder/EncoderFactory.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Encoder;
|
||||
|
||||
use Domain\Normalizer\Normalizer;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class EncoderFactory
|
||||
{
|
||||
public function __construct(
|
||||
private Normalizer $normalizer
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function getEncoder(string $type): StringEncoder
|
||||
{
|
||||
return match ($type) {
|
||||
'csv', 'CSV' => new CsvEncoder($this->normalizer, columnSeparator: ',', rowSeparator: "\n"),
|
||||
'json', 'JSON' => new JsonEncoder($this->normalizer),
|
||||
default => throw new InvalidArgumentException('Invalid encoder: ' . $type)
|
||||
};
|
||||
}
|
||||
}
|
30
src/Encoder/JsonEncoder.php
Normal file
30
src/Encoder/JsonEncoder.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Encoder;
|
||||
|
||||
use Domain\Normalizer\Normalizer;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class JsonEncoder implements StringEncoder
|
||||
{
|
||||
public function __construct(
|
||||
private Normalizer $normalizer
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function encode(Collection $items): string
|
||||
{
|
||||
return json_encode(
|
||||
[
|
||||
'count' => $items->count(),
|
||||
'items' => $items->map([$this->normalizer, 'normalize'])->values()->toArray(),
|
||||
],
|
||||
JSON_UNESCAPED_SLASHES
|
||||
| JSON_UNESCAPED_UNICODE
|
||||
| JSON_UNESCAPED_LINE_TERMINATORS
|
||||
| JSON_BIGINT_AS_STRING
|
||||
| JSON_THROW_ON_ERROR
|
||||
);
|
||||
}
|
||||
}
|
10
src/Encoder/StringEncoder.php
Normal file
10
src/Encoder/StringEncoder.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Encoder;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
interface StringEncoder
|
||||
{
|
||||
public function encode(Collection $items): string;
|
||||
}
|
55
src/IO/Downloader.php
Normal file
55
src/IO/Downloader.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace IO;
|
||||
|
||||
class Downloader
|
||||
{
|
||||
/** @var resource */
|
||||
private $curl;
|
||||
|
||||
public function __construct(
|
||||
private ?string $cacheDirectory = null
|
||||
)
|
||||
{
|
||||
$this->cacheDirectory ??= dirname(__DIR__, 2) . '/var/cache';
|
||||
$this->cacheDirectory = rtrim($this->cacheDirectory, DIRECTORY_SEPARATOR);
|
||||
|
||||
$this->curl = curl_init();
|
||||
curl_setopt_array($this->curl, [
|
||||
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT x.y; Win64; x64; rv:10.0) Gecko/20100101 Firefox/10.0',
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HEADER => false,
|
||||
CURLOPT_FORBID_REUSE => false,
|
||||
CURLOPT_AUTOREFERER => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_resource($this->curl)) {
|
||||
curl_close($this->curl);
|
||||
}
|
||||
}
|
||||
|
||||
public function download(string $url, bool $addHtmlTagsToResponse = false): string
|
||||
{
|
||||
$file = $this->getCacheFile($url);
|
||||
if (file_exists($file)) {
|
||||
return file_get_contents($file);
|
||||
}
|
||||
|
||||
curl_setopt($this->curl, CURLOPT_URL, $url);
|
||||
$response = curl_exec($this->curl);
|
||||
if ($addHtmlTagsToResponse) {
|
||||
$response = sprintf('<!DOCTYPE html><html lang="en"><body>%s</body></html>', $response);
|
||||
}
|
||||
|
||||
file_put_contents($file, $response);
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function getCacheFile(string $url): string
|
||||
{
|
||||
return $this->cacheDirectory . DIRECTORY_SEPARATOR . md5($url) . '.html';
|
||||
}
|
||||
}
|
46
src/MemoryQVLScraper.php
Normal file
46
src/MemoryQVLScraper.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
use Domain\Model\MemoryConfiguration;
|
||||
use Illuminate\Support\Collection;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class MemoryQVLScraper
|
||||
{
|
||||
/**
|
||||
* @param string $html
|
||||
* @return Collection|MemoryConfiguration[]
|
||||
*/
|
||||
public function scrape(string $html): Collection
|
||||
{
|
||||
$configurations = [];
|
||||
|
||||
$crawler = new Crawler();
|
||||
$crawler->addHtmlContent($html);
|
||||
$crawler->filterXPath('//tr')->each(function (Crawler $tr) use (&$configurations) {
|
||||
$tableData = $tr->filterXPath('//td');
|
||||
if ($tableData->count() === 0) {
|
||||
return;
|
||||
}
|
||||
$configurations[] = $this->fromTableData($tableData);
|
||||
});
|
||||
|
||||
return collect($configurations);
|
||||
}
|
||||
|
||||
private function fromTableData(Crawler $tableData): MemoryConfiguration
|
||||
{
|
||||
return new MemoryConfiguration(
|
||||
type: $tableData->eq(0)->text('DDR4'),
|
||||
vendor: $tableData->eq(1)->text(),
|
||||
speed: (int)$tableData->eq(2)->text(0),
|
||||
supportedSpeed: (int)$tableData->eq(3)->text(0),
|
||||
moduleSizeHr: $tableData->eq(4)->text(),
|
||||
module: $tableData->eq(5)->text(),
|
||||
chip: $tableData->eq(6)->text(),
|
||||
isDualSided: $tableData->eq(7)->text() === 'DS',
|
||||
dimmSocketSupport: $tableData->eq(8)->text(),
|
||||
overclockingSupport: strtolower($tableData->eq(9)->text('')),
|
||||
note: $tableData->eq(10)->text()
|
||||
);
|
||||
}
|
||||
}
|
0
var/.gitignore
vendored
Normal file
0
var/.gitignore
vendored
Normal file
0
var/cache/.gitignore
vendored
Normal file
0
var/cache/.gitignore
vendored
Normal file
0
var/doc/.gitignore
vendored
Normal file
0
var/doc/.gitignore
vendored
Normal file
Loading…
Reference in New Issue
Block a user