Skip to content

Commit

Permalink
[TASK] Add compatibility for TYPO3 13
Browse files Browse the repository at this point in the history
  • Loading branch information
schliesser committed May 11, 2024
1 parent ecd84eb commit 7dfc039
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 289 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
/.travis.yml export-ignore
/.php_cs.dist export-ignore
/.php-cs-fixer.php export-ignore
/,phpstan.neon export-ignore
51 changes: 9 additions & 42 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [7.4, 8.0, 8.1, 8.2]
php-versions: [8.1, 8.2, 8.3]
steps:
- name: Checkout
uses: actions/checkout@v3
Expand All @@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [8.1]
php-versions: [8.3]
steps:
- name: Checkout
uses: actions/checkout@v3
Expand All @@ -60,11 +60,11 @@ jobs:
max-parallel: 2
matrix:
variants:
- {typo3: 13, php: 8.3}
- {typo3: 13, php: 8.2}
- {typo3: 12, php: 8.3}
- {typo3: 12, php: 8.2}
- {typo3: 12, php: 8.1}
- {typo3: 11, php: 8.1}
- {typo3: 11, php: 8.0}
- {typo3: 11, php: 7.4}

name: "Run tests with PHP ${{ matrix.variants.php }}
using TYPO3 ${{ matrix.variants.typo3 }}"
Expand Down Expand Up @@ -93,42 +93,9 @@ jobs:
"^${{ matrix.variants.typo3 }}"
--prefer-dist --no-progress --no-suggest

- name: "Run PHPStan tests"
run: composer run-script test-phpstan
# todo: move to separate task?

- name: "Run Functional tests"
run: composer run-script test-functional
tests-legacy:
runs-on: ubuntu-latest
strategy:
max-parallel: 2
matrix:
variants:
- { typo3: 10, php: 7.4 }

name: "Run tests with PHP ${{ matrix.variants.php }}
using TYPO3 ${{ matrix.variants.typo3 }}"
steps:
- uses: actions/checkout@v3

- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.variants.php }}
extensions: xml, mbstring, curl

- name: "Cache composer dependencies"
uses: actions/cache@v1
with:
path: ~/.composer/cache
key: php-${{ matrix.variants.php }}
-typo3-${{ matrix.variants.typo3 }}
-composer-${{ hashFiles('composer.json') }}
restore-keys: |
php-${{ matrix.variants.php }}
-typo3-${{ matrix.variants.typo3 }}
-composer-${{ hashFiles('composer.json') }}
- name: "Install composer dependencies"
run: composer require typo3/minimal
"^${{ matrix.variants.typo3 }}"
--prefer-dist --no-progress --no-suggest

- name: "Run Functional tests"
run: composer run-script test-functional-legacy
28 changes: 15 additions & 13 deletions .php-cs-fixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@
'blank_line_after_opening_tag' => true,
// An empty line feed must precede any configured statement.
'blank_line_before_statement' => ['statements'=>['return']],
// The body of each structure MUST be enclosed by braces. Braces should be properly placed. Body of braces should be properly indented.
'braces' => ['allow_single_line_anonymous_class_with_empty_body'=>true,'allow_single_line_closure'=>true],
'single_space_around_construct' => true,
'control_structure_braces' => true,
'control_structure_continuation_position' => true,
'declare_parentheses' => true,
'no_multiple_statements_per_line' => true,
'braces_position' => true,
'statement_indentation' => true,
// A single space or none should be between cast and variable.
'cast_spaces' => false,
// Class, trait and interface elements must be separated with one or none blank line.
Expand All @@ -30,7 +35,7 @@
// Namespace must not contain spacing, comments or PHPDoc.
'clean_namespace' => true,
// Remove extra spaces in a nullable typehint.
'compact_nullable_typehint' => true,
'compact_nullable_type_declaration' => true,
// Concatenation should be spaced according configuration.
'concat_space' => false,
// The PHP constants `true`, `false`, and `null` MUST be written using the correct casing.
Expand Down Expand Up @@ -58,7 +63,7 @@
// Spaces should be properly placed in a function declaration.
'function_declaration' => true,
// Ensure single space between function's argument and its typehint.
'function_typehint_space' => true,
'type_declaration_spaces' => true,
// Renames PHPDoc tags.
'general_phpdoc_tag_rename' => ['replacements'=>['inheritDocs'=>'inheritDoc']],
// Include/Require and file path should be divided with a single space. File path should not be placed under brackets.
Expand Down Expand Up @@ -88,9 +93,9 @@
// Function defined by PHP should be called using the correct casing.
'native_function_casing' => true,
// Native type hints for functions should use the correct case.
'native_function_type_declaration_casing' => true,
'native_type_declaration_casing' => true,
// All instances created with new keyword must be followed by braces.
'new_with_braces' => true,
'new_with_parentheses' => true,
// Master language constructs shall be used instead of aliases.
'no_alias_language_construct_call' => true,
// Replace control structure alternative syntax to use braces.
Expand Down Expand Up @@ -130,21 +135,20 @@
// There MUST NOT be spaces around offset braces.
'no_spaces_around_offset' => true,
// There MUST NOT be a space after the opening parenthesis. There MUST NOT be a space before the closing parenthesis.
'no_spaces_inside_parenthesis' => true,
'spaces_inside_parentheses' => true,
// Removes `@param`, `@return` and `@var` tags that don't provide any useful information.
'no_superfluous_phpdoc_tags' => ['allow_mixed'=>true,'allow_unused_params'=>true],
// Remove trailing commas in list function calls.
'no_trailing_comma_in_list_call' => true,
// PHP single-line arrays should not have trailing comma.
'no_trailing_comma_in_singleline_array' => true,
'no_trailing_comma_in_singleline' => true,
// Remove trailing whitespace at the end of non-blank lines.
'no_trailing_whitespace' => true,
// There MUST be no trailing spaces inside comment or PHPDoc.
'no_trailing_whitespace_in_comment' => true,
// Removes unneeded parentheses around control statements.
'no_unneeded_control_parentheses' => ['statements'=>['break','clone','continue','echo_print','return','switch_case','yield','yield_from']],
// Removes unneeded curly braces that are superfluous and aren't part of a control structure's body.
'no_unneeded_curly_braces' => ['namespaces'=>true],
'no_unneeded_braces' => true,
// Variables must be set `null` instead of using `(unset)` casting.
'no_unset_cast' => true,
// Unused `use` statements must be removed.
Expand Down Expand Up @@ -216,7 +220,7 @@
// A PHP file without end tag must always end with a single empty line feed.
'single_blank_line_at_eof' => true,
// There should be exactly one blank line before a namespace declaration.
'single_blank_line_before_namespace' => true,
'blank_lines_before_namespace' => true,
// There MUST NOT be more than one property or constant declared per statement.
'single_class_element_per_statement' => true,
// There MUST be one use keyword per declaration.
Expand All @@ -229,8 +233,6 @@
'single_line_throw' => true,
// Convert double quotes to single quotes for simple strings.
'single_quote' => true,
// Ensures a single space after language constructs.
'single_space_after_construct' => true,
// Each trait `use` must be done as single statement.
'single_trait_insert_per_statement' => true,
// Fix whitespace after a semicolon.
Expand Down
6 changes: 6 additions & 0 deletions .phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
parameters:
level: 6
paths:
- .
ignoreErrors:
- '#Variable \$_EXTKEY might not be defined.#'
39 changes: 26 additions & 13 deletions Classes/Command/CrawlSitemapCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Schliesser\Sitecrawler\Exception\InvalidFormatException;
use Schliesser\Sitecrawler\Exception\InvalidUrlException;
use Schliesser\Sitecrawler\Helper\Error;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputArgument;
Expand All @@ -16,10 +17,14 @@

class CrawlSitemapCommand extends Command
{
/** @var string[] */
public array $sitemaps = [];
/** @var string[] */
protected array $urls = [];
protected int $sitemapCount = 0;
/** @var array<Error> */
protected array $errors = [];
/** @var array<string, string> */
protected array $requestHeaders = [
'User-Agent' => 'TYPO3 sitecrawler',
];
Expand Down Expand Up @@ -132,7 +137,7 @@ protected function printErrors(OutputInterface $output): void
{
// print errors
foreach ($this->errors as $error) {
$output->writeln($error['error'] . ': ' . $error['message']);
$output->writeln($error->getCode() . ': ' . $error->getMessage());
}

// reset errors
Expand All @@ -148,7 +153,7 @@ protected function processUrlList(OutputInterface $output): void
foreach ($progressBar->iterate($this->urls) as $url) {
$result = $this->testUrl($url);
if (!$result) {
$this->errors[] = ['error' => 1633234397666, 'message' => 'Unable to fetch url: "' . $url . '"'];
$this->errors[] = new Error(1633234397666, 'Unable to fetch url: "' . $url . '"');
}
}

Expand Down Expand Up @@ -212,12 +217,15 @@ protected function getUrlListFromSitemap(string $url): void
}
}

/**
* @return string[]
*/
protected function readRobotsTxt(string $robotsTxtUrl): array
{
// Fetch sitemap urls form robots.txt
$content = $this->getUrl($robotsTxtUrl);
if (!$content) {
$this->errors[] = ['error' => 1633234519166, 'message' => 'Unable to fetch robots.txt'];
$this->errors[] = new Error(1633234519166, 'Unable to fetch robots.txt');

return [];
}
Expand All @@ -230,21 +238,25 @@ protected function readRobotsTxt(string $robotsTxtUrl): array
return $sitemaps;
}

/**
* @return mixed[]
*/
protected function getArrayFromUrl(string $url): array
{
try {
$data = $this->getUrl($url);
if (!$data) {
$this->errors[] = ['error' => 1633234217716, 'message' => 'Unable to load xml from url: "' . $url . '"'];
$this->errors[] = new Error(1633234217716, 'Unable to load xml from url: "' . $url . '"');

return [];
}
$xml = simplexml_load_string($data);
} catch (\Exception $e) {
$this->errors[] = ['error' => $e->getCode(), 'message' => $e->getMessage()];
$this->errors[] = new Error($e->getCode(), $e->getMessage());

return [];
}

// Convert SimpleXML Objects to associative array
return json_decode(json_encode($xml), true) ?: [];
}
Expand Down Expand Up @@ -273,34 +285,35 @@ protected function addUrl(string $url): void

/**
* Wrapper for GeneralUtility::getUrl() with catcher for all exceptions
*
* @return false|mixed|string
*/
protected function getUrl(string $url)
protected function getUrl(string $url): ?string
{
try {
$requestFactory = GeneralUtility::makeInstance(RequestFactory::class);
$response = $requestFactory->request($url, 'GET', ['headers' => $this->requestHeaders ?? []]);

return $response->getBody()->getContents();
} catch (\Exception $e) {
$this->errors[] = ['error' => $e->getCode(), 'message' => $e->getMessage()];
$this->errors[] = new Error($e->getCode(), $e->getMessage());

return false;
return null;
}
}

protected function testUrl(string $url)
/**
* @return mixed[]|null
*/
protected function testUrl(string $url): ?array
{
try {
$requestFactory = GeneralUtility::makeInstance(RequestFactory::class);
$response = $requestFactory->request($url, 'HEAD', ['headers' => $this->requestHeaders ?? []]);

return $response->getHeaders();
} catch (\Exception $e) {
$this->errors[] = ['error' => $e->getCode(), 'message' => $e->getMessage()];
$this->errors[] = new Error($e->getCode(), $e->getMessage());

return false;
return null;
}
}
}
22 changes: 22 additions & 0 deletions Classes/Helper/Error.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Schliesser\Sitecrawler\Helper;

class Error
{
public function __construct(readonly int $code, readonly string $message)
{
}

public function getCode(): int
{
return $this->code;
}

public function getMessage(): string
{
return $this->message;
}
}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ Since version 1.1.0 the sitecrawler can read `robots.txt` files to fetch all def

Composer based:
```bash
vendor/bin/typo3cms sitecrawler:crawl 'https://www.example.com/sitemap.xml'
vendor/bin/typo3 sitecrawler:crawl 'https://www.example.com/sitemap.xml'

# with custom request headers
vendor/bin/typo3cms sitecrawler:crawl 'https://www.example.com/sitemap.xml' '{"Authorization": "Basic dXNlcjpwYXNzd29yZA==", "Cache-Control": "no-cache"}'
vendor/bin/typo3 sitecrawler:crawl 'https://www.example.com/sitemap.xml' '{"Authorization": "Basic dXNlcjpwYXNzd29yZA==", "Cache-Control": "no-cache"}'
```
Non composer:
```bash
Expand Down
5 changes: 5 additions & 0 deletions Tests/Functional/Command/CrawlSitemapCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ protected function setUp(): void
/**
* @test
*
* @param string[] $parameters
*
* @dataProvider commandDataProvider
*/
public function crawlSitemapCommandTest(array $parameters, string $expectedOutput, string $expectedError = ''): void
Expand All @@ -47,6 +49,9 @@ public function crawlSitemapCommandTest(array $parameters, string $expectedOutpu
self::assertStringContainsString($expectedOutput, $commandOutput);
}

/**
* @return mixed[]
*/
public static function commandDataProvider(): iterable
{
yield 'No url param' => [
Expand Down
Loading

0 comments on commit 7dfc039

Please sign in to comment.