Skip to content

Commit b2aaf6b

Browse files
authored
Merge pull request #17 from aledeg/release/1.1.2
Release 1.1.2
2 parents e68fd2c + 0d86a52 commit b2aaf6b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+3811
-1245
lines changed

.github/workflows/tests.yml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: Automated tests
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
tests:
7+
runs-on: ubuntu-22.04
8+
9+
steps:
10+
- uses: actions/checkout@v3
11+
- run: make install
12+
- run: make coding-style
13+
- run: make static-analysis
14+
- run: make test-default

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ vendor/
55
var/
66
.phpunit.cache/
77
phpunit.xml
8+
.php-cs-fixer.cache

.php-cs-fixer.dist.php

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
$finder = PhpCsFixer\Finder::create()
6+
->in(__DIR__)
7+
;
8+
9+
$config = new PhpCsFixer\Config();
10+
return $config->setRules([
11+
'@PSR12' => true,
12+
'strict_param' => true,
13+
'array_syntax' => ['syntax' => 'short'],
14+
])
15+
->setFinder($finder)
16+
;

Client/Client.php

+19-4
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,23 @@
66

77
use RedditImage\Exception\ClientException;
88

9-
class Client {
9+
class Client
10+
{
1011
private string $userAgent;
1112

12-
public function __construct(string $userAgent) {
13+
public function __construct(string $userAgent)
14+
{
1315
$this->userAgent = $userAgent;
1416
}
1517

16-
public function jsonGet(string $url, array $headers = [], callable $payloadModifier = null): array {
18+
/**
19+
* @param string $url
20+
* @param string[] $headers
21+
* @param callable $payloadModifier
22+
* @return array<mixed, mixed>
23+
*/
24+
public function jsonGet(string $url, array $headers = [], callable $payloadModifier = null): array
25+
{
1726
$ch = curl_init();
1827
curl_setopt_array($ch, [
1928
CURLOPT_URL => $url,
@@ -37,7 +46,13 @@ public function jsonGet(string $url, array $headers = [], callable $payloadModif
3746
return json_decode($jsonString, true, 512, JSON_THROW_ON_ERROR);
3847
}
3948

40-
public function isAccessible(string $url, array $headers = []): bool {
49+
/**
50+
* @param string $url
51+
* @param string[] $headers
52+
* @return bool
53+
*/
54+
public function isAccessible(string $url, array $headers = []): bool
55+
{
4156
$ch = curl_init();
4257
curl_setopt_array($ch, [
4358
CURLOPT_URL => $url,

Content.php

+36-22
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@
66

77
use RedditImage\Exception\InvalidContentException;
88

9-
class Content {
10-
private string $content;
9+
class Content
10+
{
1111
private string $preprocessed = '';
1212
private string $metadata = '';
1313
private ?string $contentLink = null;
1414
private ?string $commentsLink = null;
1515
private string $raw;
1616
private string $real = '';
1717

18-
public function __construct(string $content) {
19-
$this->content = $content;
18+
public function __construct(string $content)
19+
{
2020
$this->raw = $content;
2121

2222
$this->splitContent($content);
@@ -29,7 +29,8 @@ public function __construct(string $content) {
2929
}
3030
}
3131

32-
private function isValid(): bool {
32+
private function isValid(): bool
33+
{
3334
if ($this->metadata === '') {
3435
return false;
3536
}
@@ -42,35 +43,43 @@ private function isValid(): bool {
4243
return true;
4344
}
4445

45-
public function getContentLink(): ?string {
46+
public function getContentLink(): ?string
47+
{
4648
return $this->contentLink;
4749
}
4850

49-
public function getCommentsLink(): ?string {
51+
public function getCommentsLink(): ?string
52+
{
5053
return $this->commentsLink;
5154
}
5255

53-
public function getPreprocessed(): string {
56+
public function getPreprocessed(): string
57+
{
5458
return $this->preprocessed;
5559
}
5660

57-
public function getMetadata(): string {
61+
public function getMetadata(): string
62+
{
5863
return $this->metadata;
5964
}
6065

61-
public function getRaw(): string {
66+
public function getRaw(): string
67+
{
6268
return $this->raw;
6369
}
6470

65-
public function getReal(): string {
71+
public function getReal(): string
72+
{
6673
return $this->real;
6774
}
6875

69-
public function hasBeenPreprocessed(): bool {
76+
public function hasBeenPreprocessed(): bool
77+
{
7078
return '' !== $this->preprocessed;
7179
}
7280

73-
public function hasReal(): bool {
81+
public function hasReal(): bool
82+
{
7483
return '' !== $this->real;
7584
}
7685

@@ -81,7 +90,8 @@ public function hasReal(): bool {
8190
* fetch quickly. For instance when API calls are involved. Thus we need to
8291
* separate the feed raw content from the preprocessed content.
8392
*/
84-
private function splitContent(string $content): void {
93+
private function splitContent(string $content): void
94+
{
8595
$dom = new \DomDocument('1.0', 'UTF-8');
8696
$dom->loadHTML(
8797
htmlspecialchars_decode(htmlentities(html_entity_decode($content))),
@@ -91,10 +101,10 @@ private function splitContent(string $content): void {
91101
$xpath = new \DOMXpath($dom);
92102
$redditImage = $xpath->query("//div[contains(@class,'reddit-image')]");
93103

94-
if (1 === $redditImage->length) {
104+
if ($redditImage !== false && $redditImage->length === 1) {
95105
$node = $redditImage->item(0);
96-
$this->preprocessed = $dom->saveHTML($node->parentNode->firstChild);
97-
$this->raw = $dom->saveHTML($node->parentNode->lastChild);
106+
$this->preprocessed = $dom->saveHTML($node->parentNode->firstChild) ?: '';
107+
$this->raw = $dom->saveHTML($node->parentNode->lastChild) ?: '';
98108
}
99109
}
100110

@@ -106,7 +116,8 @@ private function splitContent(string $content): void {
106116
* to the author page, the link to the current message, and the link to the
107117
* current message comment section.
108118
*/
109-
private function extractMetadata(): void {
119+
private function extractMetadata(): void
120+
{
110121
if (preg_match('#(?P<metadata>\s*?submitted.*</span>)#', $this->raw, $matches)) {
111122
$this->metadata = $matches['metadata'];
112123
}
@@ -119,7 +130,8 @@ private function extractMetadata(): void {
119130
* - content link.
120131
* - comments link.
121132
*/
122-
private function extractLinks(): void {
133+
private function extractLinks(): void
134+
{
123135
$dom = new \DomDocument('1.0', 'UTF-8');
124136
$dom->loadHTML(
125137
htmlspecialchars_decode(htmlentities(html_entity_decode($this->raw))),
@@ -134,6 +146,7 @@ private function extractLinks(): void {
134146
break;
135147
case '[comments]':
136148
$this->commentsLink = $link->getAttribute('href');
149+
// no break
137150
default:
138151
break;
139152
}
@@ -147,7 +160,8 @@ private function extractLinks(): void {
147160
* class attribute is sanitized to data-sanitized-class attribute when
148161
* processed by SimplePie.
149162
*/
150-
private function extractReal(): void {
163+
private function extractReal(): void
164+
{
151165
$dom = new \DomDocument('1.0', 'UTF-8');
152166
$dom->loadHTML(
153167
htmlspecialchars_decode(htmlentities(html_entity_decode($this->raw))),
@@ -156,9 +170,9 @@ private function extractReal(): void {
156170

157171
$xpath = new \DOMXpath($dom);
158172
$mdNode = $xpath->query("//div[contains(@data-sanitized-class,'md')]");
159-
if (1 === $mdNode->length) {
173+
if ($mdNode !== false && $mdNode->length === 1) {
160174
$node = $mdNode->item(0);
161-
$this->real = $dom->saveHTML($node);
175+
$this->real = $dom->saveHTML($node) ?: '';
162176
}
163177
}
164178
}

Exception/ClientException.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
namespace RedditImage\Exception;
66

7-
use \Exception;
7+
use Exception;
88

9-
class ClientException extends Exception {
9+
class ClientException extends Exception
10+
{
1011
}

Exception/InvalidContentException.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
namespace RedditImage\Exception;
66

7-
use \Exception;
7+
use Exception;
88

9-
class InvalidContentException extends Exception {
9+
class InvalidContentException extends Exception
10+
{
1011
}

Makefile

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
##@ General
2+
3+
.PHONY: help
4+
help: ## Display this help.
5+
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
6+
7+
##@ Setting environment
8+
.PHONY: install
9+
install: ## Install the dev environment (phpunit, phpstan, ...)
10+
@docker-compose run composer install
11+
12+
.PHONY: classmap
13+
classmap: ## Refresh classmap for autoloading
14+
@docker-compose run composer dump-autoload
15+
16+
##@ Testing
17+
.PHONY: coding-style
18+
coding-style: classmap ## Run the coding style fixer on all PHP files
19+
@docker-compose run phpcsfixer fix --allow-risky yes
20+
21+
.PHONY: static-analysis
22+
static-analysis: classmap ## Run the static analysis on all PHP files
23+
@docker-compose run phpstan analyse --memory-limit 512M
24+
25+
.PHONY: test-testsuite
26+
test-testsuite: classmap
27+
@docker-compose run phpunit --testsuite $(TESTSUITE)
28+
29+
.PHONY: test-default
30+
test-default: TESTSUITE=default
31+
test-default: test-testsuite ## Run the default testsuite
32+
33+
.PHONY: test-canary
34+
test-canary: TESTSUITE=canary
35+
test-canary: test-testsuite ## Run the canary testsuite

Media/DomElementInterface.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace RedditImage\Media;
66

7-
interface DomElementInterface {
7+
interface DomElementInterface
8+
{
89
public function toDomElement(\DomDocument $domDocument): \DomElement;
910
}

Media/Image.php

+6-3
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44

55
namespace RedditImage\Media;
66

7-
class Image implements DomElementInterface {
7+
class Image implements DomElementInterface
8+
{
89
private string $url;
910

10-
public function __construct(string $url) {
11+
public function __construct(string $url)
12+
{
1113
$this->url = $url;
1214
}
1315

14-
public function toDomElement(\DomDocument $domDocument): \DomElement {
16+
public function toDomElement(\DomDocument $domDocument): \DomElement
17+
{
1518
$image = $domDocument->createElement('img');
1619
$image->setAttribute('src', $this->url);
1720
$image->setAttribute('class', 'reddit-image');

Media/Link.php

+8-4
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,22 @@
44

55
namespace RedditImage\Media;
66

7-
class Link implements DomElementInterface {
7+
class Link implements DomElementInterface
8+
{
89
private string $url;
910

10-
public function __construct(string $url) {
11+
public function __construct(string $url)
12+
{
1113
$this->url = $url;
1214
}
1315

14-
public function toDomElement(\DomDocument $domDocument): \DomElement {
16+
public function toDomElement(\DomDocument $domDocument): \DomElement
17+
{
1518
$p = $domDocument->createElement('p');
16-
$a = $p->appendChild($domDocument->createElement('a'));
19+
$a = $domDocument->createElement('a');
1720
$a->setAttribute('href', $this->url);
1821
$a->appendChild($domDocument->createTextNode($this->url));
22+
$p->appendChild($a);
1923

2024
return $p;
2125
}

0 commit comments

Comments
 (0)