diff --git a/app/config/config.yml b/app/config/config.yml index ace558c1b..96412a383 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -45,6 +45,8 @@ framework: headers: Content-Type: 'application/json' X-Accept: 'application/json' + request_html_function.client: + scope: '.*' # Twig Configuration twig: diff --git a/app/config/services.yml b/app/config/services.yml index e23f459d8..0e8ef4ff6 100644 --- a/app/config/services.yml +++ b/app/config/services.yml @@ -34,7 +34,7 @@ services: Wallabag\: resource: '../../src/*' - exclude: ['../../src/{Consumer,Controller,Entity,ExpressionLanguage,DataFixtures,Redis}', '../../src/Event/*Event.php'] + exclude: ['../../src/{Consumer,Controller,Entity,DataFixtures,Redis}', '../../src/Event/*Event.php'] # controllers are imported separately to make sure services can be injected # as action arguments even if you don't extend any base controller class diff --git a/src/ExpressionLanguage/AuthenticatorProvider.php b/src/ExpressionLanguage/AuthenticatorProvider.php index 63822aaba..25c748d3e 100644 --- a/src/ExpressionLanguage/AuthenticatorProvider.php +++ b/src/ExpressionLanguage/AuthenticatorProvider.php @@ -2,21 +2,18 @@ namespace Wallabag\ExpressionLanguage; -use GuzzleHttp\ClientInterface; use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\ExpressionLanguage\ExpressionFunction; use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; class AuthenticatorProvider implements ExpressionFunctionProviderInterface { - /** - * @var ClientInterface - */ - private $guzzle; + private HttpClientInterface $requestHtmlFunctionClient; - public function __construct(ClientInterface $guzzle) + public function __construct(HttpClientInterface $requestHtmlFunctionClient) { - $this->guzzle = $guzzle; + $this->requestHtmlFunctionClient = $requestHtmlFunctionClient; } public function getFunctions(): array @@ -38,7 +35,7 @@ class AuthenticatorProvider implements ExpressionFunctionProviderInterface throw new \Exception('Not supported'); }, function (array $arguments, $uri) { - return $this->guzzle->get($uri, $options)->getBody(); + return $this->requestHtmlFunctionClient->request('GET', $uri)->getContent(); } ); } diff --git a/src/SiteConfig/LoginFormAuthenticator.php b/src/SiteConfig/LoginFormAuthenticator.php index ab1d83970..c857413d5 100644 --- a/src/SiteConfig/LoginFormAuthenticator.php +++ b/src/SiteConfig/LoginFormAuthenticator.php @@ -10,6 +10,13 @@ use Wallabag\ExpressionLanguage\AuthenticatorProvider; class LoginFormAuthenticator { + private AuthenticatorProvider $authenticatorProvider; + + public function __construct(AuthenticatorProvider $authenticatorProvider) + { + $this->authenticatorProvider = $authenticatorProvider; + } + /** * Logs the configured user on the given Guzzle client. * @@ -20,7 +27,7 @@ class LoginFormAuthenticator $postFields = [ $siteConfig->getUsernameField() => $siteConfig->getUsername(), $siteConfig->getPasswordField() => $siteConfig->getPassword(), - ] + $this->getExtraFields($siteConfig, $guzzle); + ] + $this->getExtraFields($siteConfig); $guzzle->post( $siteConfig->getLoginUri(), @@ -77,13 +84,13 @@ class LoginFormAuthenticator * * @return array */ - private function getExtraFields(SiteConfig $siteConfig, ClientInterface $guzzle) + private function getExtraFields(SiteConfig $siteConfig) { $extraFields = []; foreach ($siteConfig->getExtraFields() as $fieldName => $fieldValue) { if ('@=' === substr($fieldValue, 0, 2)) { - $expressionLanguage = $this->getExpressionLanguage($guzzle); + $expressionLanguage = $this->getExpressionLanguage(); $fieldValue = $expressionLanguage->evaluate( substr($fieldValue, 2), [ @@ -101,11 +108,11 @@ class LoginFormAuthenticator /** * @return ExpressionLanguage */ - private function getExpressionLanguage(ClientInterface $guzzle) + private function getExpressionLanguage() { return new ExpressionLanguage( null, - [new AuthenticatorProvider($guzzle)] + [$this->authenticatorProvider] ); } } diff --git a/tests/SiteConfig/LoginFormAuthenticatorTest.php b/tests/SiteConfig/LoginFormAuthenticatorTest.php index a1bac9207..e4f930754 100644 --- a/tests/SiteConfig/LoginFormAuthenticatorTest.php +++ b/tests/SiteConfig/LoginFormAuthenticatorTest.php @@ -7,6 +7,9 @@ use GuzzleHttp\Message\Response; use GuzzleHttp\Stream\Stream; use GuzzleHttp\Subscriber\Mock; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Component\HttpClient\Response\MockResponse; +use Wallabag\ExpressionLanguage\AuthenticatorProvider; use Wallabag\SiteConfig\LoginFormAuthenticator; use Wallabag\SiteConfig\SiteConfig; @@ -22,6 +25,8 @@ class LoginFormAuthenticatorTest extends TestCase $guzzle = new Client(); $guzzle->getEmitter()->attach(new Mock([$response])); + $mockHttpClient = new MockHttpClient([new MockResponse('', ['http_code' => 200, 'response_headers' => ['content-type' => 'text/html']])]); + $siteConfig = new SiteConfig([ 'host' => 'example.com', 'loginUri' => 'http://example.com/login', @@ -35,7 +40,8 @@ class LoginFormAuthenticatorTest extends TestCase 'password' => 'unkn0wn', ]); - $auth = new LoginFormAuthenticator(); + $authenticatorProvider = new AuthenticatorProvider($mockHttpClient); + $auth = new LoginFormAuthenticator($authenticatorProvider); $res = $auth->login($siteConfig, $guzzle); $this->assertInstanceOf(LoginFormAuthenticator::class, $res); @@ -51,6 +57,8 @@ class LoginFormAuthenticatorTest extends TestCase $guzzle = new Client(); $guzzle->getEmitter()->attach(new Mock([$response, $response])); + $mockHttpClient = new MockHttpClient([new MockResponse('', ['http_code' => 200, 'response_headers' => ['content-type' => 'text/html']])]); + $siteConfig = new SiteConfig([ 'host' => 'example.com', 'loginUri' => 'http://example.com/login', @@ -65,7 +73,8 @@ class LoginFormAuthenticatorTest extends TestCase 'password' => 'unkn0wn', ]); - $auth = new LoginFormAuthenticator(); + $authenticatorProvider = new AuthenticatorProvider($mockHttpClient); + $auth = new LoginFormAuthenticator($authenticatorProvider); $res = $auth->login($siteConfig, $guzzle); $this->assertInstanceOf(LoginFormAuthenticator::class, $res); @@ -86,6 +95,8 @@ class LoginFormAuthenticatorTest extends TestCase ->method('getStatusCode') ->willReturn(200); + $mockHttpClient = new MockHttpClient([new MockResponse(file_get_contents(__DIR__ . '/../fixtures/aoc.media.html'), ['http_code' => 200, 'response_headers' => ['content-type' => 'text/html']])]); + $client = $this->getMockBuilder(Client::class) ->disableOriginalConstructor() ->getMock(); @@ -128,7 +139,8 @@ class LoginFormAuthenticatorTest extends TestCase 'password' => 'unkn0wn', ]); - $auth = new LoginFormAuthenticator(); + $authenticatorProvider = new AuthenticatorProvider($mockHttpClient); + $auth = new LoginFormAuthenticator($authenticatorProvider); $res = $auth->login($siteConfig, $client); $this->assertInstanceOf(LoginFormAuthenticator::class, $res); @@ -148,6 +160,8 @@ class LoginFormAuthenticatorTest extends TestCase ->method('getStatusCode') ->willReturn(200); + $mockHttpClient = new MockHttpClient([new MockResponse(file_get_contents(__DIR__ . '/../fixtures/nextinpact-login.html'), ['http_code' => 200, 'response_headers' => ['content-type' => 'text/html']])]); + $client = $this->getMockBuilder(Client::class) ->disableOriginalConstructor() ->getMock(); @@ -194,7 +208,8 @@ class LoginFormAuthenticatorTest extends TestCase 'password' => 'unkn0wn', ]); - $auth = new LoginFormAuthenticator(); + $authenticatorProvider = new AuthenticatorProvider($mockHttpClient); + $auth = new LoginFormAuthenticator($authenticatorProvider); $res = $auth->login($siteConfig, $client); $this->assertInstanceOf(LoginFormAuthenticator::class, $res); @@ -210,7 +225,10 @@ class LoginFormAuthenticatorTest extends TestCase 'password' => 'unkn0wn', ]); - $auth = new LoginFormAuthenticator(); + $mockHttpClient = new MockHttpClient(); + + $authenticatorProvider = new AuthenticatorProvider($mockHttpClient); + $auth = new LoginFormAuthenticator($authenticatorProvider); $loginRequired = $auth->isLoginRequired($siteConfig, file_get_contents(__DIR__ . '/../fixtures/nextinpact-login.html')); $this->assertFalse($loginRequired); @@ -227,7 +245,10 @@ class LoginFormAuthenticatorTest extends TestCase 'notLoggedInXpath' => '//h2[@class="title_reserve_article"]', ]); - $auth = new LoginFormAuthenticator(); + $mockHttpClient = new MockHttpClient(); + + $authenticatorProvider = new AuthenticatorProvider($mockHttpClient); + $auth = new LoginFormAuthenticator($authenticatorProvider); $loginRequired = $auth->isLoginRequired($siteConfig, file_get_contents(__DIR__ . '/../fixtures/nextinpact-article.html')); $this->assertTrue($loginRequired);