From dd3e65385ee07fcab32d3f0fa603d6168787a175 Mon Sep 17 00:00:00 2001 From: Peter Gribanov Date: Mon, 16 Nov 2020 22:52:25 +0300 Subject: [PATCH] use absolute URLs --- README.md | 112 ++++++-------- UPGRADE.md | 83 +++++------ src/Location.php | 4 +- src/Render/PlainTextSitemapIndexRender.php | 13 +- src/Render/PlainTextSitemapRender.php | 21 +-- src/Render/XMLWriterSitemapIndexRender.php | 15 +- src/Render/XMLWriterSitemapRender.php | 24 +-- src/Stream/WritingSplitIndexStream.php | 43 +----- src/Stream/WritingSplitStream.php | 9 +- src/Url/Language.php | 37 +---- src/Url/Priority.php | 4 +- tests/Builder/Url/MultiUrlBuilderTest.php | 6 +- tests/LocationTest.php | 23 +-- .../PlainTextSitemapIndexRenderTest.php | 32 ++-- tests/Render/PlainTextSitemapRenderTest.php | 66 ++++----- .../XMLWriterSitemapIndexRenderTest.php | 84 +++++------ tests/Render/XMLWriterSitemapRenderTest.php | 104 ++++++------- tests/Sitemap/SitemapTest.php | 26 ++-- tests/Stream/LoggerStreamTest.php | 4 +- tests/Stream/MultiStreamTest.php | 8 +- tests/Stream/OutputStreamTest.php | 19 +-- tests/Stream/WritingIndexStreamTest.php | 12 +- tests/Stream/WritingSplitIndexStreamTest.php | 78 +++------- tests/Stream/WritingSplitStreamTest.php | 25 ++-- tests/Stream/WritingStreamTest.php | 19 +-- tests/Url/LanguageTest.php | 42 ++---- tests/Url/PriorityTest.php | 26 ++-- tests/Url/UrlTest.php | 140 +++++++++--------- 28 files changed, 460 insertions(+), 619 deletions(-) diff --git a/README.md b/README.md index 44df6f3..b24f690 100644 --- a/README.md +++ b/README.md @@ -61,28 +61,25 @@ composer require gpslab/sitemap // URLs on your site $urls = [ Url::create( - '/', // loc + 'https://example.com/', // loc new \DateTimeImmutable('2020-06-15 13:39:46'), // lastmod ChangeFrequency::always(), // changefreq 10 // priority ), Url::create( - '/contacts.html', + 'https://example.com/contacts.html', new \DateTimeImmutable('2020-05-26 09:28:12'), ChangeFrequency::monthly(), 7 ), - Url::create('/about.html'), + Url::create('https://example.com/about.html'), ]; // file into which we will write a sitemap $filename = __DIR__.'/sitemap.xml'; -// web path to pages on your site -$web_path = 'https://example.com'; - // configure stream -$render = new PlainTextSitemapRender($web_path); +$render = new PlainTextSitemapRender(); $writer = new TempFileWriter(); $stream = new WritingStream($render, $writer, $filename); @@ -183,42 +180,42 @@ region. // URLs on your site $urls = [ Url::create( - '/english/page.html', + 'https://example.com/english/page.html', new \DateTimeImmutable('2020-06-15 13:39:46'), ChangeFrequency::monthly(), 7, [ - 'de' => '/deutsch/page.html', - 'de-ch' => '/schweiz-deutsch/page.html', - 'en' => '/english/page.html', + 'de' => 'https://example.com/deutsch/page.html', + 'de-ch' => 'https://example.com/schweiz-deutsch/page.html', + 'en' => 'https://example.com/english/page.html', 'fr' => 'https://example.fr', - 'x-default' => '/english/page.html', + 'x-default' => 'https://example.com/english/page.html', ] ), Url::create( - '/deutsch/page.html', + 'https://example.com/deutsch/page.html', new \DateTimeImmutable('2020-06-15 13:39:46'), ChangeFrequency::monthly(), 7, [ - 'de' => '/deutsch/page.html', - 'de-ch' => '/schweiz-deutsch/page.html', - 'en' => '/english/page.html', + 'de' => 'https://example.com/deutsch/page.html', + 'de-ch' => 'https://example.com/schweiz-deutsch/page.html', + 'en' => 'https://example.com/english/page.html', 'fr' => 'https://example.fr', - 'x-default' => '/english/page.html', + 'x-default' => 'https://example.com/english/page.html', ] ), Url::create( - '/schweiz-deutsch/page.html', + 'https://example.com/schweiz-deutsch/page.html', new \DateTimeImmutable('2020-06-15 13:39:46'), ChangeFrequency::monthly(), 7, [ - 'de' => '/deutsch/page.html', - 'de-ch' => '/schweiz-deutsch/page.html', - 'en' => '/english/page.html', + 'de' => 'https://example.com/deutsch/page.html', + 'de-ch' => 'https://example.com/schweiz-deutsch/page.html', + 'en' => 'https://example.com/english/page.html', 'fr' => 'https://example.fr', - 'x-default' => '/english/page.html', + 'x-default' => 'https://example.com/english/page.html', ] ), ]; @@ -229,10 +226,10 @@ You can simplify the creation of URLs for localized versions of the same page wi ```php $urls = Url::createLanguageUrls( [ - 'de' => '/deutsch/page.html', - 'de-ch' => '/schweiz-deutsch/page.html', - 'en' => '/english/page.html', - 'x-default' => '/english/page.html', + 'de' => 'https://example.com/deutsch/page.html', + 'de-ch' => 'https://example.com/schweiz-deutsch/page.html', + 'en' => 'https://example.com/english/page.html', + 'x-default' => 'https://example.com/english/page.html', ], new \DateTimeImmutable('2020-06-15 13:39:46'), ChangeFrequency::monthly(), @@ -293,19 +290,19 @@ class MySiteUrlBuilder implements UrlBuilder // add URLs on your site return new \ArrayIterator([ Url::create( - '/', // loc + 'https://example.com/', // loc new \DateTimeImmutable('2020-06-15 13:39:46'), // lastmod ChangeFrequency::always(), // changefreq 10 // priority ), Url::create( - '/contacts.html', + 'https://example.com/contacts.html', new \DateTimeImmutable('2020-05-26 09:28:12'), ChangeFrequency::monthly(), 7 ), Url::create( - '/about.html', + 'https://example.com/about.html', new \DateTimeImmutable('2020-05-02 17:12:38'), ChangeFrequency::monthly(), 7 @@ -339,14 +336,14 @@ class ArticlesUrlBuilder implements UrlBuilder // smart URL automatically fills fields that it can yield Url::createSmart( - sprintf('/article/%d', $row['id']), + sprintf('https://example.com/article/%d', $row['id']), $update_at ); } // link to section yield Url::create( - '/article/', + 'https://example.com/article/', $section_update_at ?: new \DateTimeImmutable('-1 day'), ChangeFrequency::daily(), 9 @@ -367,11 +364,8 @@ $builders = new MultiUrlBuilder([ // file into which we will write a sitemap $filename = __DIR__.'/sitemap.xml'; -// web path to pages on your site -$web_path = 'https://example.com'; - // configure stream -$render = new PlainTextSitemapRender($web_path); +$render = new PlainTextSitemapRender(); $writer = new TempFileWriter(); $stream = new WritingStream($render, $writer, $filename); @@ -392,19 +386,16 @@ have already created portions of the Sitemap, you can simply create the Sitemap // file into which we will write a sitemap $filename = __DIR__.'/sitemap.xml'; -// web path to the sitemap.xml on your site -$web_path = 'https://example.com'; - // configure stream -$render = new PlainTextSitemapIndexRender($web_path); +$render = new PlainTextSitemapIndexRender(); $writer = new TempFileWriter(); $stream = new WritingIndexStream($render, $writer, $filename); // build sitemap.xml index $stream->open(); -$stream->pushSitemap(new Sitemap('/sitemap_main.xml', new \DateTimeImmutable('-1 hour'))); -$stream->pushSitemap(new Sitemap('/sitemap_news.xml', new \DateTimeImmutable('-1 hour'))); -$stream->pushSitemap(new Sitemap('/sitemap_articles.xml', new \DateTimeImmutable('-1 hour'))); +$stream->pushSitemap(new Sitemap('https://example.com/sitemap_main.xml', new \DateTimeImmutable('-1 hour'))); +$stream->pushSitemap(new Sitemap('https://example.com/sitemap_news.xml', new \DateTimeImmutable('-1 hour'))); +$stream->pushSitemap(new Sitemap('https://example.com/sitemap_articles.xml', new \DateTimeImmutable('-1 hour'))); $stream->close(); ``` @@ -429,20 +420,17 @@ $builders = new MultiUrlBuilder([ // file into which we will write a sitemap $index_filename = __DIR__.'/sitemap.xml'; -// web path to the sitemap.xml on your site -$index_web_path = 'https://example.com'; - -$index_render = new PlainTextSitemapIndexRender($index_web_path); +$index_render = new PlainTextSitemapIndexRender(); $index_writer = new TempFileWriter(); // file into which we will write a sitemap part // filename should contain a directive like "%d" $part_filename = __DIR__.'/sitemap%d.xml'; -// web path to pages on your site -$part_web_path = 'https://example.com'; +// web path to the sitemap.xml on your site +$part_web_path = 'https://example.com/sitemap%d.xml'; -$part_render = new PlainTextSitemapRender($part_web_path); +$part_render = new PlainTextSitemapRender(); // separate writer for part // it's better not to use one writer as a part writer and a index writer // this can cause conflicts in the writer @@ -455,7 +443,8 @@ $stream = new WritingSplitIndexStream( $index_writer, $part_writer, $index_filename, - $part_filename + $part_filename, + $part_web_path ); $stream->open(); @@ -472,7 +461,7 @@ foreach ($builders as $url) { } // you can add a link to a sitemap created earlier -$stream->pushSitemap(new Sitemap('/sitemap_news.xml', new \DateTimeImmutable('-1 hour'))); +$stream->pushSitemap(new Sitemap('https://example.com/sitemap_news.xml', new \DateTimeImmutable('-1 hour'))); $stream->close(); ``` @@ -502,18 +491,12 @@ can use a lot of memory.* // file into which we will write a sitemap $index_filename = __DIR__.'/sitemap.xml'; -// web path to the sitemap.xml on your site -$index_web_path = 'https://example.com'; - -$index_render = new PlainTextSitemapIndexRender($index_web_path); +$index_render = new PlainTextSitemapIndexRender(); $index_writer = new TempFileWriter(); -// web path to pages on your site -$part_web_path = 'https://example.com'; - // separate writer for part $part_writer = new TempFileWriter(); -$part_render = new PlainTextSitemapRender($part_web_path); +$part_render = new PlainTextSitemapRender(); // create a stream for news @@ -610,12 +593,13 @@ You can use a composition of streams. $stream = new MultiStream( new LoggerStream(/* $logger */), new WritingSplitIndexStream( - new PlainTextSitemapIndexRender('https://example.com'), - new PlainTextSitemapRender('https://example.com'), + new PlainTextSitemapIndexRender(), + new PlainTextSitemapRender(), new TempFileWriter(), new GzipTempFileWriter(9), __DIR__.'/sitemap.xml', - __DIR__.'/sitemap%d.xml.gz' + __DIR__.'/sitemap%d.xml.gz', + 'https://example.com/sitemap%d.xml.gz', ) ); ``` @@ -623,7 +607,7 @@ $stream = new MultiStream( Streaming to file and compress result without index. ```php -$render = new PlainTextSitemapRender('https://example.com'); +$render = new PlainTextSitemapRender(); $stream = new MultiStream( new LoggerStream(/* $logger */), @@ -635,7 +619,7 @@ $stream = new MultiStream( Streaming to file and output buffer. ```php -$render = new PlainTextSitemapRender('https://example.com'); +$render = new PlainTextSitemapRender(); $stream = new MultiStream( new LoggerStream(/* $logger */), diff --git a/UPGRADE.md b/UPGRADE.md index 408b1cc..328935d 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -34,7 +34,7 @@ ``` * The `$host` argument in `RenderIndexFileStream::__construct()` was removed. -* The `$web_path` argument in `PlainTextSitemapIndexRender::__construct()` was added. +* The `$web_path` argument in `PlainTextSitemapIndexRender::__construct()` was removed. Before: @@ -47,44 +47,10 @@ After: ```php - $web_path = 'https://example.com'; // No slash in end of path! - $index_render = new PlainTextSitemapIndexRender($web_path); + $index_render = new PlainTextSitemapIndexRender(); $index_stream = new RenderFileStream($index_render, $stream, $filename_index); ``` -* The `$web_path` argument in `PlainTextSitemapRender::__construct()` was added. - - Before: - - ```php - $render = new PlainTextSitemapRender(); - $render->url(Url::create('https://example.com')); - $render->url(Url::create('https://example.com/about')); - ``` - - After: - - ```php - $web_path = 'https://example.com'; // No slash in end of path! - $render = new PlainTextSitemapRender($web_path); - $render->url(Url::create('/')); - $render->url(Url::create('/about')); - ``` - -* The `$priority` in `URL` class was changed from `string` to `int`. - - Before: - - ```php - $url = Url::create('/contacts.html', new \DateTimeImmutable('-1 month'), ChangeFrequency::MONTHLY, '0.7'); - ``` - - After: - - ```php - $url = Url::create('/contacts.html', new \DateTimeImmutable('-1 month'), ChangeFrequency::monthly(), 7); - ``` - * The `CallbackStream` was removed. * The `RenderGzipFileStream` was removed. Use `WritingStream` instead. @@ -135,13 +101,12 @@ ```php $index_filename = __DIR__.'/sitemap.xml'; - $index_web_path = 'https://example.com'; $part_filename = __DIR__.'/sitemap%d.xml'; - $part_web_path = 'https://example.com'; + $part_web_path = 'https://example.com/sitemap%d.xml'; - $index_render = new PlainTextSitemapIndexRender($index_web_path); + $index_render = new PlainTextSitemapIndexRender(); $index_writer = new TempFileWriter(); - $part_render = new PlainTextSitemapRender($part_web_path); + $part_render = new PlainTextSitemapRender(); $part_writer = new TempFileWriter(); $stream = new WritingSplitIndexStream( @@ -150,7 +115,8 @@ $index_writer, $part_writer, $index_filename, - $part_filename + $part_filename, + $part_web_path ); ``` @@ -173,7 +139,7 @@ ```php - $url = Url::create('/contacts.html', new \DateTimeImmutable('-1 month'), ChangeFrequency::MONTHLY, '0.7'); + $url = Url::create('https://example.com/contacts.html', new \DateTimeImmutable('-1 month'), ChangeFrequency::MONTHLY, '0.7'); ``` Or @@ -181,7 +147,7 @@ ```php $url = new Url( - new Location('/contacts.html'), + new Location('https://example.com/contacts.html'), new \DateTimeImmutable('-1 month'), ChangeFrequency::monthly(), Priority::create(7) @@ -199,5 +165,34 @@ After: ```php - $url = Url::createSmart('/article/123'); + $url = Url::createSmart('https://example.com/article/123'); + ``` + +* Use absolute URL in `Url` class. + + Before: + + ```php + $url = Url::create('/contacts.html'); + ``` + + After: + + ```php + $url = Url::create('https://example.com/contacts.html'); + ``` + +* Allow use `int` and `float` as `$priority` in `URL` class. + + Before: + + ```php + $url = Url::create('/contacts.html', new \DateTimeImmutable('-1 month'), ChangeFrequency::MONTHLY, '0.7'); + ``` + + After: + + ```php + $url = Url::create('https://example.com/contacts.html', new \DateTimeImmutable('-1 month'), ChangeFrequency::monthly(), 7); + $url = Url::create('https://example.com/contacts.html', new \DateTimeImmutable('-1 month'), ChangeFrequency::monthly(), .7); ``` diff --git a/src/Location.php b/src/Location.php index 879b37f..ec2da5e 100644 --- a/src/Location.php +++ b/src/Location.php @@ -38,9 +38,7 @@ public function __construct(string $location) throw LocationTooLongException::tooLong($location, self::MAX_LENGTH); } - if (($location && !in_array($location[0], ['/', '?', '#'], true)) || - filter_var(sprintf('https://example.com%s', $location), FILTER_VALIDATE_URL) === false - ) { + if (filter_var($location, FILTER_VALIDATE_URL) === false) { throw InvalidLocationException::invalid($location); } diff --git a/src/Render/PlainTextSitemapIndexRender.php b/src/Render/PlainTextSitemapIndexRender.php index f5957e0..2148f00 100644 --- a/src/Render/PlainTextSitemapIndexRender.php +++ b/src/Render/PlainTextSitemapIndexRender.php @@ -14,23 +14,16 @@ final class PlainTextSitemapIndexRender implements SitemapIndexRender { - /** - * @var string - */ - private $web_path; - /** * @var bool */ private $validating; /** - * @param string $web_path - * @param bool $validating + * @param bool $validating */ - public function __construct(string $web_path, bool $validating = true) + public function __construct(bool $validating = true) { - $this->web_path = $web_path; $this->validating = $validating; } @@ -69,7 +62,7 @@ public function end(): string public function sitemap(Sitemap $sitemap): string { $result = ''; - $result .= ''.htmlspecialchars($this->web_path.$sitemap->getLocation()).''; + $result .= ''.htmlspecialchars((string) $sitemap->getLocation()).''; if ($sitemap->getLastModify()) { $result .= ''.$sitemap->getLastModify()->format('c').''; diff --git a/src/Render/PlainTextSitemapRender.php b/src/Render/PlainTextSitemapRender.php index 2b44f1b..cda6af2 100644 --- a/src/Render/PlainTextSitemapRender.php +++ b/src/Render/PlainTextSitemapRender.php @@ -16,23 +16,16 @@ final class PlainTextSitemapRender implements SitemapRender { - /** - * @var string - */ - private $web_path; - /** * @var bool */ private $validating; /** - * @param string $web_path - * @param bool $validating + * @param bool $validating */ - public function __construct(string $web_path, bool $validating = true) + public function __construct(bool $validating = true) { - $this->web_path = $web_path; $this->validating = $validating; } @@ -71,7 +64,7 @@ public function end(): string */ public function url(Url $url): string { - $location = htmlspecialchars($this->web_path.$url->getLocation()); + $location = htmlspecialchars((string) $url->getLocation()); if (strlen($location) >= Location::MAX_LENGTH) { throw LocationTooLongException::tooLong($location, Location::MAX_LENGTH); @@ -93,13 +86,7 @@ public function url(Url $url): string } foreach ($url->getLanguages() as $language) { - // alternate URLs do not need to be in the same domain - if ($language->isLocalLocation()) { - $location = htmlspecialchars($this->web_path.$language->getLocation()); - } else { - $location = $language->getLocation(); - } - + $location = htmlspecialchars((string) $language->getLocation()); $result .= ''; } diff --git a/src/Render/XMLWriterSitemapIndexRender.php b/src/Render/XMLWriterSitemapIndexRender.php index e028da5..a5f2b75 100644 --- a/src/Render/XMLWriterSitemapIndexRender.php +++ b/src/Render/XMLWriterSitemapIndexRender.php @@ -24,11 +24,6 @@ final class XMLWriterSitemapIndexRender implements SitemapIndexRender */ private $writer; - /** - * @var string - */ - private $web_path; - /** * @var bool */ @@ -40,13 +35,11 @@ final class XMLWriterSitemapIndexRender implements SitemapIndexRender private $use_indent; /** - * @param string $web_path - * @param bool $validating - * @param bool $use_indent + * @param bool $validating + * @param bool $use_indent */ - public function __construct(string $web_path, bool $validating = true, bool $use_indent = false) + public function __construct(bool $validating = true, bool $use_indent = false) { - $this->web_path = $web_path; $this->validating = $validating; $this->use_indent = $use_indent; } @@ -118,7 +111,7 @@ public function sitemap(Sitemap $sitemap): string } $this->writer->startElement('sitemap'); - $this->writer->writeElement('loc', $this->web_path.$sitemap->getLocation()); + $this->writer->writeElement('loc', (string) $sitemap->getLocation()); if ($sitemap->getLastModify()) { $this->writer->writeElement('lastmod', $sitemap->getLastModify()->format('c')); diff --git a/src/Render/XMLWriterSitemapRender.php b/src/Render/XMLWriterSitemapRender.php index b946c4d..89e812e 100644 --- a/src/Render/XMLWriterSitemapRender.php +++ b/src/Render/XMLWriterSitemapRender.php @@ -26,11 +26,6 @@ final class XMLWriterSitemapRender implements SitemapRender */ private $writer; - /** - * @var string - */ - private $web_path; - /** * @var bool */ @@ -42,13 +37,11 @@ final class XMLWriterSitemapRender implements SitemapRender private $use_indent; /** - * @param string $web_path - * @param bool $validating - * @param bool $use_indent + * @param bool $validating + * @param bool $use_indent */ - public function __construct(string $web_path, bool $validating = true, bool $use_indent = false) + public function __construct(bool $validating = true, bool $use_indent = false) { - $this->web_path = $web_path; $this->validating = $validating; $this->use_indent = $use_indent; } @@ -120,14 +113,14 @@ public function url(Url $url): string $this->start(); } - $location = htmlspecialchars($this->web_path.$url->getLocation()); + $location = htmlspecialchars((string) $url->getLocation()); if (strlen($location) >= Location::MAX_LENGTH) { throw LocationTooLongException::tooLong($location, Location::MAX_LENGTH); } $this->writer->startElement('url'); - $this->writer->writeElement('loc', $this->web_path.$url->getLocation()); + $this->writer->writeElement('loc', (string) $url->getLocation()); if ($url->getLastModify() instanceof \DateTimeInterface) { $this->writer->writeElement('lastmod', $url->getLastModify()->format('c')); @@ -142,12 +135,7 @@ public function url(Url $url): string } foreach ($url->getLanguages() as $language) { - // alternate URLs do not need to be in the same domain - if ($language->isLocalLocation()) { - $location = htmlspecialchars($this->web_path.$language->getLocation()); - } else { - $location = $language->getLocation(); - } + $location = htmlspecialchars((string) $language->getLocation()); $this->writer->startElement('xhtml:link'); $this->writer->writeAttribute('rel', 'alternate'); diff --git a/src/Stream/WritingSplitIndexStream.php b/src/Stream/WritingSplitIndexStream.php index 75f2901..1562a0d 100644 --- a/src/Stream/WritingSplitIndexStream.php +++ b/src/Stream/WritingSplitIndexStream.php @@ -110,8 +110,8 @@ public function __construct( Writer $index_writer, Writer $part_writer, string $index_filename, - string $part_filename_pattern = '', - string $part_web_path_pattern = '' + string $part_filename_pattern, + string $part_web_path_pattern ) { // conflict warning if ($index_writer === $part_writer) { @@ -122,9 +122,7 @@ public function __construct( ); } - if (!$part_filename_pattern) { - $this->part_filename_pattern = $this->buildIndexPartFilenamePattern($index_filename); - } elseif ( + if ( sprintf($part_filename_pattern, $this->index) === $part_filename_pattern || sprintf($part_filename_pattern, Limiter::SITEMAPS_LIMIT) === $part_filename_pattern ) { @@ -133,14 +131,15 @@ public function __construct( $this->part_filename_pattern = $part_filename_pattern; } - if ($part_web_path_pattern && ( + if ( sprintf($part_web_path_pattern, $this->index) === $part_web_path_pattern || - sprintf($part_web_path_pattern, Limiter::SITEMAPS_LIMIT) === $part_web_path_pattern - )) { + sprintf($part_web_path_pattern, Limiter::SITEMAPS_LIMIT) === $part_web_path_pattern || + filter_var(sprintf($part_web_path_pattern, $this->index), FILTER_VALIDATE_URL) === false + ) { throw SplitIndexException::invalidPartWebPathPattern($part_web_path_pattern); } - $this->part_web_path_pattern = $part_web_path_pattern ?: '/'.basename($this->part_filename_pattern); + $this->part_web_path_pattern = $part_web_path_pattern; $this->index_render = $index_render; $this->part_render = $part_render; @@ -269,30 +268,4 @@ private function addIndexPartToIndex(int $index): void new \DateTimeImmutable() ))); } - - /** - * @param string $path - * - * @return string - */ - private function buildIndexPartFilenamePattern(string $path): string - { - $basename = basename($path); - - // use explode() for correct add index - // sitemap.xml -> sitemap%d.xml - // sitemap.xml.gz -> sitemap%d.xml.gz - [$filename, $extension] = explode('.', $basename, 2) + ['', '']; - - // use substr() for save original structure of path - // sitemap.xml -> sitemap%d.xml - // /sitemap.xml -> /sitemap%d.xml - // if we use dirname() and concatenation we get: - // sitemap.xml -> ./sitemap%d.xml - // /sitemap.xml -> //sitemap%d.xml - // these paths are equivalent, but strings are different - $dirname = substr($path, 0, strlen($basename) * -1); - - return sprintf('%s%s%s.%s', $dirname, $filename ?: 'sitemap', '%d', $extension ?: 'xml'); - } } diff --git a/src/Stream/WritingSplitStream.php b/src/Stream/WritingSplitStream.php index df2c3c3..7144d9e 100644 --- a/src/Stream/WritingSplitStream.php +++ b/src/Stream/WritingSplitStream.php @@ -75,8 +75,8 @@ final class WritingSplitStream implements SplitStream /** * @param SitemapRender $render * @param Writer $writer - * @param string $filename_pattern * @param string $web_path_pattern + * @param string $filename_pattern * * @throws SplitIndexException */ @@ -84,7 +84,7 @@ public function __construct( SitemapRender $render, Writer $writer, string $filename_pattern, - string $web_path_pattern = '' + string $web_path_pattern ) { if ( sprintf($filename_pattern, $this->index) === $filename_pattern || @@ -93,11 +93,10 @@ public function __construct( throw SplitIndexException::invalidPartFilenamePattern($filename_pattern); } - $web_path_pattern = $web_path_pattern ?: '/'.basename($filename_pattern); - if ( sprintf($web_path_pattern, $this->index) === $web_path_pattern || - sprintf($web_path_pattern, Limiter::SITEMAPS_LIMIT) === $web_path_pattern + sprintf($web_path_pattern, Limiter::SITEMAPS_LIMIT) === $web_path_pattern || + filter_var(sprintf($web_path_pattern, $this->index), FILTER_VALIDATE_URL) === false ) { throw SplitIndexException::invalidPartWebPathPattern($web_path_pattern); } diff --git a/src/Url/Language.php b/src/Url/Language.php index a7e950c..29a94f2 100644 --- a/src/Url/Language.php +++ b/src/Url/Language.php @@ -10,7 +10,7 @@ namespace GpsLab\Component\Sitemap\Url; -use GpsLab\Component\Sitemap\Exception\InvalidLocationException; +use GpsLab\Component\Sitemap\Location; use GpsLab\Component\Sitemap\Url\Exception\InvalidLanguageException; final class Language @@ -31,38 +31,25 @@ final class Language private $language; /** - * @var string + * @var Location */ private $location; /** - * @var bool - */ - private $local_location; - - /** - * @param string $language - * @param string $location + * @param string $language + * @param Location|string $location * * @throws InvalidLanguageException */ - public function __construct(string $language, string $location) + public function __construct(string $language, $location) { // language in ISO 639-1 and optionally a region in ISO 3166-1 Alpha 2 if ($language !== self::UNMATCHED_LANGUAGE && !preg_match('/^[a-z]{2}([-_][a-z]{2})?$/i', $language)) { throw InvalidLanguageException::invalid($language); } - // localization pages do not need to be in the same domain - $this->local_location = !$location || in_array($location[0], ['/', '?', '#'], true); - $validate_url = $this->local_location ? sprintf('https://example.com%s', $location) : $location; - - if (filter_var($validate_url, FILTER_VALIDATE_URL) === false) { - throw InvalidLocationException::invalid($location); - } - $this->language = $language; - $this->location = $location; + $this->location = $location instanceof Location ? $location : new Location($location); } /** @@ -74,18 +61,10 @@ public function getLanguage(): string } /** - * @return string + * @return Location */ - public function getLocation(): string + public function getLocation(): Location { return $this->location; } - - /** - * @return bool - */ - public function isLocalLocation(): bool - { - return $this->local_location; - } } diff --git a/src/Url/Priority.php b/src/Url/Priority.php index b2ea89c..ba7782b 100644 --- a/src/Url/Priority.php +++ b/src/Url/Priority.php @@ -95,8 +95,10 @@ public static function create($priority): self */ public static function createByLocation(Location $location): self { + $location = parse_url($location->getLocation(), PHP_URL_PATH); + $location = trim((string) $location, '/'); // number of slashes - $num = count(array_filter(explode('/', trim((string) $location, '/')))); + $num = count(array_filter(explode('/', $location))); if (!$num) { return self::safeCreate('1.0'); diff --git a/tests/Builder/Url/MultiUrlBuilderTest.php b/tests/Builder/Url/MultiUrlBuilderTest.php index 11027ea..b7480d0 100644 --- a/tests/Builder/Url/MultiUrlBuilderTest.php +++ b/tests/Builder/Url/MultiUrlBuilderTest.php @@ -22,12 +22,12 @@ public function testIterate(): void { $urls = []; $builders = [ - $this->createUrlBuilder($urls, '/news', 3), - $this->createUrlBuilder($urls, '/articles', 3), + $this->createUrlBuilder($urls, 'https://example.com/news', 3), + $this->createUrlBuilder($urls, 'https://example.com/articles', 3), ]; $builder = new MultiUrlBuilder($builders); - $builder->add($this->createUrlBuilder($urls, '/posts', 3)); + $builder->add($this->createUrlBuilder($urls, 'https://example.com/posts', 3)); foreach ($builder as $i => $url) { self::assertEquals($urls[$i], $url); diff --git a/tests/LocationTest.php b/tests/LocationTest.php index 29cfe58..8446c04 100644 --- a/tests/LocationTest.php +++ b/tests/LocationTest.php @@ -23,13 +23,13 @@ final class LocationTest extends TestCase public function getValidLocations(): array { return [ - [''], - ['/'], - ['#about'], - ['?foo=bar'], - ['?foo=bar&baz=123'], - ['/index.html'], - ['/about/index.html'], + ['https://example.com'], + ['https://example.com/'], + ['https://example.com#about'], + ['https://example.com?foo=bar'], + ['https://example.com?foo=bar&baz=123'], + ['https://example.com/index.html'], + ['https://example.com/about/index.html'], ]; } @@ -52,9 +52,13 @@ public function testValidLocation(string $location): void public function getInvalidLocations(): array { return [ + [''], + ['/'], ['../'], ['index.html'], + ['?foo=bar'], ['&foo=bar'], + ['#'], ['№'], ['@'], ['\\'], @@ -77,8 +81,9 @@ public function testLocationTooLong(): void { $this->expectException(LocationTooLongException::class); - $location_max_length = Location::MAX_LENGTH; + $location = 'https://example.com/'; + $location .= str_repeat('f', Location::MAX_LENGTH - strlen($location) + 1 /* overflow */); - new Location(str_repeat('f', $location_max_length + 1)); + new Location($location); } } diff --git a/tests/Render/PlainTextSitemapIndexRenderTest.php b/tests/Render/PlainTextSitemapIndexRenderTest.php index 1cdc5ce..0585c47 100644 --- a/tests/Render/PlainTextSitemapIndexRenderTest.php +++ b/tests/Render/PlainTextSitemapIndexRenderTest.php @@ -16,8 +16,6 @@ final class PlainTextSitemapIndexRenderTest extends TestCase { - private const WEB_PATH = 'https://example.com'; - /** * @var PlainTextSitemapIndexRender */ @@ -25,7 +23,7 @@ final class PlainTextSitemapIndexRenderTest extends TestCase protected function setUp(): void { - $this->render = new PlainTextSitemapIndexRender(self::WEB_PATH); + $this->render = new PlainTextSitemapIndexRender(); } /** @@ -58,7 +56,7 @@ public function getValidating(): array */ public function testStart(bool $validating, string $start_teg): void { - $render = new PlainTextSitemapIndexRender(self::WEB_PATH, $validating); + $render = new PlainTextSitemapIndexRender($validating); $expected = ''.PHP_EOL.$start_teg; self::assertEquals($expected, $render->start()); @@ -73,13 +71,13 @@ public function testEnd(): void public function testSitemap(): void { - $path = '/sitemap1.xml'; + $url = 'https://example.com/sitemap1.xml'; $expected = ''. - ''.self::WEB_PATH.$path.''. + ''.$url.''. ''; - self::assertEquals($expected, $this->render->sitemap(new Sitemap($path))); + self::assertEquals($expected, $this->render->sitemap(new Sitemap($url))); } /** @@ -101,14 +99,14 @@ public function getLastMod(): array */ public function testSitemapWithLastMod(?\DateTimeInterface $last_modify): void { - $path = '/sitemap1.xml'; + $url = 'https://example.com/sitemap1.xml'; $expected = ''. - ''.self::WEB_PATH.$path.''. + ''.$url.''. ($last_modify ? sprintf('%s', $last_modify->format('c')) : ''). ''; - self::assertEquals($expected, $this->render->sitemap(new Sitemap($path, $last_modify))); + self::assertEquals($expected, $this->render->sitemap(new Sitemap($url, $last_modify))); } /** @@ -119,24 +117,24 @@ public function testSitemapWithLastMod(?\DateTimeInterface $last_modify): void */ public function testStreamRender(bool $validating, string $start_teg): void { - $render = new PlainTextSitemapIndexRender(self::WEB_PATH, $validating); - $path1 = '/sitemap1.xml'; + $render = new PlainTextSitemapIndexRender($validating); + $url1 = 'https://example.com/sitemap1.xml'; // test escaping - $path2 = '/sitemap1.xml?foo=\'bar\'&baz=">"&zaz=<'; + $url2 = 'https://example.com/sitemap1.xml?foo=\'bar\'&baz=">"&zaz=<'; - $actual = $render->start().$render->sitemap(new Sitemap($path1)); + $actual = $render->start().$render->sitemap(new Sitemap($url1)); // render end string right after render first Sitemap and before another Sitemaps // this is necessary to calculate the size of the sitemap index in bytes $end = $render->end(); - $actual .= $render->sitemap(new Sitemap($path2)).$end; + $actual .= $render->sitemap(new Sitemap($url2)).$end; $expected = ''.PHP_EOL. $start_teg. ''. - ''.self::WEB_PATH.$path1.''. + ''.$url1.''. ''. ''. - ''.htmlspecialchars(self::WEB_PATH.$path2).''. + ''.htmlspecialchars($url2).''. ''. ''.PHP_EOL ; diff --git a/tests/Render/PlainTextSitemapRenderTest.php b/tests/Render/PlainTextSitemapRenderTest.php index d554dfc..297a922 100644 --- a/tests/Render/PlainTextSitemapRenderTest.php +++ b/tests/Render/PlainTextSitemapRenderTest.php @@ -19,8 +19,6 @@ final class PlainTextSitemapRenderTest extends TestCase { - private const WEB_PATH = 'https://example.com'; - /** * @var PlainTextSitemapRender */ @@ -28,7 +26,7 @@ final class PlainTextSitemapRenderTest extends TestCase protected function setUp(): void { - $this->render = new PlainTextSitemapRender(self::WEB_PATH); + $this->render = new PlainTextSitemapRender(); } /** @@ -65,7 +63,7 @@ public function getValidating(): array */ public function testStart(bool $validating, string $start_teg): void { - $render = new PlainTextSitemapRender(self::WEB_PATH, $validating); + $render = new PlainTextSitemapRender($validating); $expected = ''.PHP_EOL.$start_teg; self::assertEquals($expected, $render->start()); @@ -84,20 +82,26 @@ public function testEnd(): void public function getUrls(): array { return [ - [Url::create('/')], - [Url::create('/', new \DateTimeImmutable('-1 day'))], - [Url::create('/', null, ChangeFrequency::WEEKLY)], - [Url::create('/', null, null, 10)], - [Url::create('/', null, ChangeFrequency::WEEKLY, 10)], - [Url::create('/', new \DateTimeImmutable('-1 day'), null, 10)], - [Url::create('/', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, null)], - [Url::create('/', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, 10)], - [Url::create('/?foo=\'bar\'&baz=">"&zaz=<')], // test escaping - [Url::create('/english/page.html', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, 10, [ - 'de' => 'https://de.example.com/page.html', - 'de-ch' => '/schweiz-deutsch/page.html', - 'en' => '/english/page.html', - ])], + [Url::create('https://example.com/')], + [Url::create('https://example.com/', new \DateTimeImmutable('-1 day'))], + [Url::create('https://example.com/', null, ChangeFrequency::WEEKLY)], + [Url::create('https://example.com/', null, null, 10)], + [Url::create('https://example.com/', null, ChangeFrequency::WEEKLY, 10)], + [Url::create('https://example.com/', new \DateTimeImmutable('-1 day'), null, 10)], + [Url::create('https://example.com/', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, null)], + [Url::create('https://example.com/', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, 10)], + [Url::create('https://example.com/?foo=\'bar\'&baz=">"&zaz=<')], // test escaping + [Url::create( + 'https://example.com/english/page.html', + new \DateTimeImmutable('-1 day'), + ChangeFrequency::WEEKLY, + 10, + [ + 'de' => 'https://de.example.com/page.html', + 'de-ch' => 'https://example.com/schweiz-deutsch/page.html', + 'en' => 'https://example.com/english/page.html', + ]), + ], ]; } @@ -109,7 +113,7 @@ public function getUrls(): array public function testUrl(Url $url): void { $expected = ''; - $expected .= ''.htmlspecialchars(self::WEB_PATH.$url->getLocation()).''; + $expected .= ''.htmlspecialchars((string) $url->getLocation()).''; if ($url->getLastModify()) { $expected .= ''.$url->getLastModify()->format('c').''; @@ -124,13 +128,7 @@ public function testUrl(Url $url): void } foreach ($url->getLanguages() as $language) { - // alternate URLs do not need to be in the same domain - if ($language->isLocalLocation()) { - $location = htmlspecialchars(self::WEB_PATH.$language->getLocation()); - } else { - $location = $language->getLocation(); - } - + $location = htmlspecialchars((string) $language->getLocation()); $expected .= ''; } @@ -147,15 +145,15 @@ public function testUrl(Url $url): void */ public function testStreamRender(bool $validating, string $start_teg): void { - $render = new PlainTextSitemapRender(self::WEB_PATH, $validating); + $render = new PlainTextSitemapRender($validating); $url1 = Url::create( - '/', + 'https://example.com/', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, 10 ); $url2 = Url::create( - '/about', + 'https://example.com/about', new \DateTimeImmutable('-1 month'), ChangeFrequency::YEARLY, 9 @@ -170,13 +168,13 @@ public function testStreamRender(bool $validating, string $start_teg): void $expected = ''.PHP_EOL. $start_teg. ''. - ''.htmlspecialchars(self::WEB_PATH.$url1->getLocation()).''. + ''.htmlspecialchars((string) $url1->getLocation()).''. ''.$url1->getLastModify()->format('c').''. ''.$url1->getChangeFrequency().''. ''.$url1->getPriority().''. ''. ''. - ''.htmlspecialchars(self::WEB_PATH.$url2->getLocation()).''. + ''.htmlspecialchars((string) $url2->getLocation()).''. ''.$url2->getLastModify()->format('c').''. ''.$url2->getChangeFrequency().''. ''.$url2->getPriority().''. @@ -193,10 +191,10 @@ public function testLocationTooLong(): void $location_max_length = Location::MAX_LENGTH; - $web_path = str_repeat('/', (int) ceil($location_max_length / 2)); - $location = str_repeat('/', (int) ceil($location_max_length / 2) + 1 /* overflow */); + $location = 'https://example.com/'; + $location .= str_repeat('f', $location_max_length - strlen($location) + 1 /* overflow */); - $render = new PlainTextSitemapRender($web_path); + $render = new PlainTextSitemapRender(); $render->url(Url::create($location)); } } diff --git a/tests/Render/XMLWriterSitemapIndexRenderTest.php b/tests/Render/XMLWriterSitemapIndexRenderTest.php index def86e7..1bef5c9 100644 --- a/tests/Render/XMLWriterSitemapIndexRenderTest.php +++ b/tests/Render/XMLWriterSitemapIndexRenderTest.php @@ -21,8 +21,6 @@ final class XMLWriterSitemapIndexRenderTest extends TestCase */ private const EOL = "\n"; - private const WEB_PATH = 'https://example.com'; - /** * @var XMLWriterSitemapIndexRender */ @@ -30,7 +28,7 @@ final class XMLWriterSitemapIndexRenderTest extends TestCase protected function setUp(): void { - $this->render = new XMLWriterSitemapIndexRender(self::WEB_PATH); + $this->render = new XMLWriterSitemapIndexRender(); } /** @@ -63,7 +61,7 @@ public function getValidating(): array */ public function testStart(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapIndexRender(self::WEB_PATH, $validating); + $render = new XMLWriterSitemapIndexRender($validating); $expected = ''.self::EOL.$start_teg.self::EOL; self::assertEquals($expected, $render->start()); @@ -77,7 +75,7 @@ public function testStart(bool $validating, string $start_teg): void */ public function testDoubleStart(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapIndexRender(self::WEB_PATH, $validating); + $render = new XMLWriterSitemapIndexRender($validating); $expected = ''.self::EOL.$start_teg.self::EOL; self::assertEquals($expected, $render->start()); @@ -97,7 +95,7 @@ public function testEndNotStarted(): void */ public function testStartEnd(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapIndexRender(self::WEB_PATH, $validating); + $render = new XMLWriterSitemapIndexRender($validating); $expected = ''.self::EOL. $start_teg.self::EOL. ''.self::EOL @@ -108,29 +106,29 @@ public function testStartEnd(bool $validating, string $start_teg): void public function testAddSitemapInNotStarted(): void { - $path = '/sitemap1.xml'; + $url = 'https://example.com/sitemap1.xml'; $expected = ''. - ''.self::WEB_PATH.$path.''. + ''.$url.''. '' ; - self::assertEquals($expected, $this->render->sitemap(new Sitemap($path))); + self::assertEquals($expected, $this->render->sitemap(new Sitemap($url))); } public function testAddSitemapInNotStartedUseIndent(): void { - $render = new XMLWriterSitemapIndexRender(self::WEB_PATH, false, true); - $path = '/sitemap1.xml'; + $render = new XMLWriterSitemapIndexRender(false, true); + $url = 'https://example.com/sitemap1.xml'; $expected = ' '.self::EOL. - ' '.self::WEB_PATH.$path.''.self::EOL. + ' '.$url.''.self::EOL. ' '.self::EOL ; - self::assertEquals($expected, $render->sitemap(new Sitemap($path))); + self::assertEquals($expected, $render->sitemap(new Sitemap($url))); } /** @@ -141,18 +139,18 @@ public function testAddSitemapInNotStartedUseIndent(): void */ public function testSitemap(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapIndexRender(self::WEB_PATH, $validating); - $path = '/sitemap1.xml'; + $render = new XMLWriterSitemapIndexRender($validating); + $url = 'https://example.com/sitemap1.xml'; $expected = ''.self::EOL. $start_teg.self::EOL. ''. - ''.self::WEB_PATH.$path.''. + ''.$url.''. ''. ''.self::EOL ; - self::assertEquals($expected, $render->start().$render->sitemap(new Sitemap($path)).$render->end()); + self::assertEquals($expected, $render->start().$render->sitemap(new Sitemap($url)).$render->end()); } /** @@ -183,19 +181,19 @@ public function testSitemapWithLastModify( bool $validating, string $start_teg ): void { - $render = new XMLWriterSitemapIndexRender(self::WEB_PATH, $validating); - $path = '/sitemap1.xml'; + $render = new XMLWriterSitemapIndexRender($validating); + $url = 'https://example.com/sitemap1.xml'; $expected = ''.self::EOL. $start_teg.self::EOL. ''. - ''.self::WEB_PATH.$path.''. + ''.$url.''. ''.$last_modify->format('c').''. ''. ''.self::EOL ; - $actual = $render->start().$render->sitemap(new Sitemap($path, $last_modify)).$render->end(); + $actual = $render->start().$render->sitemap(new Sitemap($url, $last_modify)).$render->end(); self::assertEquals($expected, $actual); } @@ -207,18 +205,18 @@ public function testSitemapWithLastModify( */ public function testSitemapUseIndent(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapIndexRender(self::WEB_PATH, $validating, true); - $path = '/sitemap1.xml'; + $render = new XMLWriterSitemapIndexRender($validating, true); + $url = 'https://example.com/sitemap1.xml'; $expected = ''.self::EOL. $start_teg.self::EOL. ' '.self::EOL. - ' '.self::WEB_PATH.$path.''.self::EOL. + ' '.$url.''.self::EOL. ' '.self::EOL. ''.self::EOL ; - self::assertEquals($expected, $render->start().$render->sitemap(new Sitemap($path)).$render->end()); + self::assertEquals($expected, $render->start().$render->sitemap(new Sitemap($url)).$render->end()); } /** @@ -233,19 +231,19 @@ public function testSitemapUseIndentWithLastModify( bool $validating, string $start_teg ): void { - $render = new XMLWriterSitemapIndexRender(self::WEB_PATH, $validating, true); - $path = '/sitemap1.xml'; + $render = new XMLWriterSitemapIndexRender($validating, true); + $url = 'https://example.com/sitemap1.xml'; $expected = ''.self::EOL. $start_teg.self::EOL. ' '.self::EOL. - ' '.self::WEB_PATH.$path.''.self::EOL. + ' '.$url.''.self::EOL. ' '.$last_modify->format('c').''.self::EOL. ' '.self::EOL. ''.self::EOL ; - $actual = $render->start().$render->sitemap(new Sitemap($path, $last_modify)).$render->end(); + $actual = $render->start().$render->sitemap(new Sitemap($url, $last_modify)).$render->end(); self::assertEquals($expected, $actual); } @@ -258,24 +256,24 @@ public function testSitemapUseIndentWithLastModify( */ public function testStreamRender(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapIndexRender(self::WEB_PATH, $validating); - $path1 = '/sitemap1.xml'; + $render = new XMLWriterSitemapIndexRender($validating); + $url1 = 'https://example.com/sitemap1.xml'; // test escaping - $path2 = '/sitemap1.xml?foo=\'bar\'&baz=">"&zaz=<'; + $url2 = 'https://example.com/sitemap1.xml?foo=\'bar\'&baz=">"&zaz=<'; - $actual = $render->start().$render->sitemap(new Sitemap($path1)); + $actual = $render->start().$render->sitemap(new Sitemap($url1)); // render end string right after render first Sitemap and before another Sitemaps // this is necessary to calculate the size of the sitemap index in bytes $end = $render->end(); - $actual .= $render->sitemap(new Sitemap($path2)).$end; + $actual .= $render->sitemap(new Sitemap($url2)).$end; $expected = ''.self::EOL. $start_teg.self::EOL. ''. - ''.self::WEB_PATH.$path1.''. + ''.$url1.''. ''. ''. - ''.htmlspecialchars(self::WEB_PATH.$path2).''. + ''.htmlspecialchars($url2).''. ''. ''.self::EOL ; @@ -291,23 +289,23 @@ public function testStreamRender(bool $validating, string $start_teg): void */ public function testStreamRenderUseIndent(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapIndexRender(self::WEB_PATH, $validating, true); - $path1 = '/sitemap1.xml'; - $path2 = '/sitemap1.xml'; + $render = new XMLWriterSitemapIndexRender($validating, true); + $url1 = 'https://example.com/sitemap1.xml'; + $url2 = 'https://example.com/sitemap1.xml'; - $actual = $render->start().$render->sitemap(new Sitemap($path1)); + $actual = $render->start().$render->sitemap(new Sitemap($url1)); // render end string right after render first Sitemap and before another Sitemaps // this is necessary to calculate the size of the sitemap index in bytes $end = $render->end(); - $actual .= $render->sitemap(new Sitemap($path2)).$end; + $actual .= $render->sitemap(new Sitemap($url2)).$end; $expected = ''.self::EOL. $start_teg.self::EOL. ' '.self::EOL. - ' '.self::WEB_PATH.$path1.''.self::EOL. + ' '.$url1.''.self::EOL. ' '.self::EOL. ' '.self::EOL. - ' '.self::WEB_PATH.$path2.''.self::EOL. + ' '.$url2.''.self::EOL. ' '.self::EOL. ''.self::EOL ; diff --git a/tests/Render/XMLWriterSitemapRenderTest.php b/tests/Render/XMLWriterSitemapRenderTest.php index 94f000a..519b385 100644 --- a/tests/Render/XMLWriterSitemapRenderTest.php +++ b/tests/Render/XMLWriterSitemapRenderTest.php @@ -24,8 +24,6 @@ final class XMLWriterSitemapRenderTest extends TestCase */ private const EOL = "\n"; - private const WEB_PATH = 'https://example.com'; - /** * @var XMLWriterSitemapRender */ @@ -33,7 +31,7 @@ final class XMLWriterSitemapRenderTest extends TestCase protected function setUp(): void { - $this->render = new XMLWriterSitemapRender(self::WEB_PATH); + $this->render = new XMLWriterSitemapRender(); } /** @@ -70,7 +68,7 @@ public function getValidating(): array */ public function testStart(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapRender(self::WEB_PATH, $validating); + $render = new XMLWriterSitemapRender($validating); $expected = ''.self::EOL.$start_teg.self::EOL; self::assertEquals($expected, $render->start()); @@ -84,7 +82,7 @@ public function testStart(bool $validating, string $start_teg): void */ public function testDoubleStart(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapRender(self::WEB_PATH, $validating); + $render = new XMLWriterSitemapRender($validating); $expected = ''.self::EOL.$start_teg.self::EOL; self::assertEquals($expected, $render->start()); @@ -104,7 +102,7 @@ public function testEndNotStarted(): void */ public function testStartEnd(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapRender(self::WEB_PATH, $validating); + $render = new XMLWriterSitemapRender($validating); $expected = ''.self::EOL. $start_teg.self::EOL. ''.self::EOL @@ -119,20 +117,26 @@ public function testStartEnd(bool $validating, string $start_teg): void public function getUrls(): array { return [ - [Url::create('/')], - [Url::create('/', new \DateTimeImmutable('-1 day'))], - [Url::create('/', null, ChangeFrequency::WEEKLY)], - [Url::create('/', null, null, 10)], - [Url::create('/', null, ChangeFrequency::WEEKLY, 10)], - [Url::create('/', new \DateTimeImmutable('-1 day'), null, 10)], - [Url::create('/', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, null)], - [Url::create('/', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, 10)], - [Url::create('/?foo=\'bar\'&baz=">"&zaz=<')], // test escaping - [Url::create('/english/page.html', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, 10, [ - 'de' => 'https://de.example.com/page.html', - 'de-ch' => '/schweiz-deutsch/page.html', - 'en' => '/english/page.html', - ])], + [Url::create('https://example.com/')], + [Url::create('https://example.com/', new \DateTimeImmutable('-1 day'))], + [Url::create('https://example.com/', null, ChangeFrequency::WEEKLY)], + [Url::create('https://example.com/', null, null, 10)], + [Url::create('https://example.com/', null, ChangeFrequency::WEEKLY, 10)], + [Url::create('https://example.com/', new \DateTimeImmutable('-1 day'), null, 10)], + [Url::create('https://example.com/', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, null)], + [Url::create('https://example.com/', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, 10)], + [Url::create('https://example.com/?foo=\'bar\'&baz=">"&zaz=<')], // test escaping + [Url::create( + 'https://example.com/english/page.html', + new \DateTimeImmutable('-1 day'), + ChangeFrequency::WEEKLY, + 10, + [ + 'de' => 'https://de.example.com/page.html', + 'de-ch' => 'https://example.com/schweiz-deutsch/page.html', + 'en' => 'https://example.com/english/page.html', + ]), + ], ]; } @@ -144,7 +148,7 @@ public function getUrls(): array public function testAddUrlInNotStarted(Url $url): void { $expected = ''; - $expected .= ''.htmlspecialchars(self::WEB_PATH.$url->getLocation()).''; + $expected .= ''.htmlspecialchars((string) $url->getLocation()).''; if ($url->getLastModify()) { $expected .= ''.$url->getLastModify()->format('c').''; @@ -159,13 +163,7 @@ public function testAddUrlInNotStarted(Url $url): void } foreach ($url->getLanguages() as $language) { - // alternate URLs do not need to be in the same domain - if ($language->isLocalLocation()) { - $location = htmlspecialchars(self::WEB_PATH.$language->getLocation()); - } else { - $location = $language->getLocation(); - } - + $location = htmlspecialchars((string) $language->getLocation()); $expected .= ''; } @@ -181,10 +179,10 @@ public function testAddUrlInNotStarted(Url $url): void */ public function testAddUrlInNotStartedUseIndent(Url $url): void { - $render = new XMLWriterSitemapRender(self::WEB_PATH, false, true); + $render = new XMLWriterSitemapRender(false, true); $expected = ' '.self::EOL; - $expected .= ' '.htmlspecialchars(self::WEB_PATH.$url->getLocation()).''.self::EOL; + $expected .= ' '.htmlspecialchars((string) $url->getLocation()).''.self::EOL; if ($url->getLastModify()) { $expected .= ' '.$url->getLastModify()->format('c').''.self::EOL; @@ -199,13 +197,7 @@ public function testAddUrlInNotStartedUseIndent(Url $url): void } foreach ($url->getLanguages() as $language) { - // alternate URLs do not need to be in the same domain - if ($language->isLocalLocation()) { - $location = htmlspecialchars(self::WEB_PATH.$language->getLocation()); - } else { - $location = $language->getLocation(); - } - + $location = htmlspecialchars((string) $language->getLocation()); $expected .= ' '.self::EOL; } @@ -222,9 +214,9 @@ public function testAddUrlInNotStartedUseIndent(Url $url): void */ public function testUrl(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapRender(self::WEB_PATH, $validating); + $render = new XMLWriterSitemapRender($validating); $url = Url::create( - '/', + 'https://example.com/', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, 10 @@ -233,7 +225,7 @@ public function testUrl(bool $validating, string $start_teg): void $expected = ''.self::EOL. $start_teg.self::EOL. ''. - ''.htmlspecialchars(self::WEB_PATH.$url->getLocation()).''. + ''.htmlspecialchars((string) $url->getLocation()).''. ''.$url->getLastModify()->format('c').''. ''.$url->getChangeFrequency().''. ''.$url->getPriority().''. @@ -252,9 +244,9 @@ public function testUrl(bool $validating, string $start_teg): void */ public function testUrlUseIndent(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapRender(self::WEB_PATH, $validating, true); + $render = new XMLWriterSitemapRender($validating, true); $url = Url::create( - '/', + 'https://example.com/', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, 10 @@ -263,7 +255,7 @@ public function testUrlUseIndent(bool $validating, string $start_teg): void $expected = ''.self::EOL. $start_teg.self::EOL. ' '.self::EOL. - ' '.htmlspecialchars(self::WEB_PATH.$url->getLocation()).''.self::EOL. + ' '.htmlspecialchars((string) $url->getLocation()).''.self::EOL. ' '.$url->getLastModify()->format('c').''.self::EOL. ' '.$url->getChangeFrequency().''.self::EOL. ' '.$url->getPriority().''.self::EOL. @@ -282,15 +274,15 @@ public function testUrlUseIndent(bool $validating, string $start_teg): void */ public function testStreamRender(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapRender(self::WEB_PATH, $validating); + $render = new XMLWriterSitemapRender($validating); $url1 = Url::create( - '/', + 'https://example.com/', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, 10 ); $url2 = Url::create( - '/about', + 'https://example.com/about', new \DateTimeImmutable('-1 month'), ChangeFrequency::YEARLY, 9 @@ -305,13 +297,13 @@ public function testStreamRender(bool $validating, string $start_teg): void $expected = ''.self::EOL. $start_teg.self::EOL. ''. - ''.htmlspecialchars(self::WEB_PATH.$url1->getLocation()).''. + ''.htmlspecialchars((string) $url1->getLocation()).''. ''.$url1->getLastModify()->format('c').''. ''.$url1->getChangeFrequency().''. ''.$url1->getPriority().''. ''. ''. - ''.htmlspecialchars(self::WEB_PATH.$url2->getLocation()).''. + ''.htmlspecialchars((string) $url2->getLocation()).''. ''.$url2->getLastModify()->format('c').''. ''.$url2->getChangeFrequency().''. ''.$url2->getPriority().''. @@ -330,15 +322,15 @@ public function testStreamRender(bool $validating, string $start_teg): void */ public function testStreamRenderUseIndent(bool $validating, string $start_teg): void { - $render = new XMLWriterSitemapRender(self::WEB_PATH, $validating, true); + $render = new XMLWriterSitemapRender($validating, true); $url1 = Url::create( - '/', + 'https://example.com/', new \DateTimeImmutable('-1 day'), ChangeFrequency::WEEKLY, 10 ); $url2 = Url::create( - '/about', + 'https://example.com/about', new \DateTimeImmutable('-1 month'), ChangeFrequency::YEARLY, 9 @@ -353,13 +345,13 @@ public function testStreamRenderUseIndent(bool $validating, string $start_teg): $expected = ''.self::EOL. $start_teg.self::EOL. ' '.self::EOL. - ' '.htmlspecialchars(self::WEB_PATH.$url1->getLocation()).''.self::EOL. + ' '.htmlspecialchars((string) $url1->getLocation()).''.self::EOL. ' '.$url1->getLastModify()->format('c').''.self::EOL. ' '.$url1->getChangeFrequency().''.self::EOL. ' '.$url1->getPriority().''.self::EOL. ' '.self::EOL. ' '.self::EOL. - ' '.htmlspecialchars(self::WEB_PATH.$url2->getLocation()).''.self::EOL. + ' '.htmlspecialchars((string) $url2->getLocation()).''.self::EOL. ' '.$url2->getLastModify()->format('c').''.self::EOL. ' '.$url2->getChangeFrequency().''.self::EOL. ' '.$url2->getPriority().''.self::EOL. @@ -376,10 +368,10 @@ public function testLocationTooLong(): void $location_max_length = Location::MAX_LENGTH; - $web_path = str_repeat('/', (int) ceil($location_max_length / 2)); - $location = str_repeat('/', (int) ceil($location_max_length / 2) + 1 /* overflow */); + $location = 'https://example.com/'; + $location .= str_repeat('f', $location_max_length - strlen($location) + 1 /* overflow */); - $render = new XMLWriterSitemapRender($web_path); + $render = new XMLWriterSitemapRender(); $render->url(Url::create($location)); } } diff --git a/tests/Sitemap/SitemapTest.php b/tests/Sitemap/SitemapTest.php index 5b8da37..0ca7146 100644 --- a/tests/Sitemap/SitemapTest.php +++ b/tests/Sitemap/SitemapTest.php @@ -23,16 +23,16 @@ final class SitemapTest extends TestCase public function getSitemap(): array { return [ - ['', null], - ['/', new \DateTime('-1 day')], - ['/', new \DateTimeImmutable('-1 day')], - ['/index.html', null], - ['/about/index.html', null], - ['?', null], - ['?foo=bar', null], - ['?foo=bar&baz=123', null], - ['#', null], - ['#about', null], + ['https://example.com', null], + ['https://example.com/', new \DateTime('-1 day')], + ['https://example.com/', new \DateTimeImmutable('-1 day')], + ['https://example.com/index.html', null], + ['https://example.com/about/index.html', null], + ['https://example.com?', null], + ['https://example.com?foo=bar', null], + ['https://example.com?foo=bar&baz=123', null], + ['https://example.com#', null], + ['https://example.com#about', null], ]; } @@ -56,9 +56,13 @@ public function testSitemap(string $location, ?\DateTimeInterface $last_modify = public function getInvalidLocations(): array { return [ + [''], + ['/'], ['../'], ['index.html'], + ['?foo=bar'], ['&foo=bar'], + ['#'], ['№'], ['@'], ['\\'], @@ -81,6 +85,6 @@ public function testInvalidLastModify(): void { $this->expectException(InvalidLastModifyException::class); - new Sitemap('/', new \DateTimeImmutable('+1 minutes')); + new Sitemap('https://example.com/', new \DateTimeImmutable('+1 minutes')); } } diff --git a/tests/Stream/LoggerStreamTest.php b/tests/Stream/LoggerStreamTest.php index a3625d5..2b4bdc3 100644 --- a/tests/Stream/LoggerStreamTest.php +++ b/tests/Stream/LoggerStreamTest.php @@ -41,8 +41,8 @@ public function testPush(): void $this->stream->open(); $this->stream->close(); - $url1 = Url::create('/'); - $url2 = Url::createSmart('/'); + $url1 = Url::create('https://example.com/'); + $url2 = Url::createSmart('https://example.com/'); $this->logger ->expects(self::at(0)) diff --git a/tests/Stream/MultiStreamTest.php b/tests/Stream/MultiStreamTest.php index 0f84e7a..8c0027e 100644 --- a/tests/Stream/MultiStreamTest.php +++ b/tests/Stream/MultiStreamTest.php @@ -104,9 +104,9 @@ public function testPush(array $substreams): void { $i = 0; $urls = [ - Url::create('/foo'), - Url::create('/bar'), - Url::create('/baz'), + Url::create('https://example.com/foo'), + Url::create('https://example.com/bar'), + Url::create('https://example.com/baz'), ]; $stream = new MultiStream(...$substreams); @@ -139,7 +139,7 @@ public function testPush(array $substreams): void public function testReset(array $substreams): void { $i = 0; - $url = Url::create('/foo'); + $url = Url::create('https://example.com/foo'); $stream = new MultiStream(...$substreams); foreach ($substreams as $substream) { diff --git a/tests/Stream/OutputStreamTest.php b/tests/Stream/OutputStreamTest.php index d01cf68..f01a5ea 100644 --- a/tests/Stream/OutputStreamTest.php +++ b/tests/Stream/OutputStreamTest.php @@ -111,7 +111,7 @@ public function testAlreadyClosed(): void public function testPushNotOpened(): void { $this->expectException(StreamStateException::class); - $this->stream->push(Url::create('/')); + $this->stream->push(Url::create('https://example.com/')); } public function testPushClosed(): void @@ -120,15 +120,15 @@ public function testPushClosed(): void $this->close(); $this->expectException(StreamStateException::class); - $this->stream->push(Url::create('/')); + $this->stream->push(Url::create('https://example.com/')); } public function testPush(): void { $urls = [ - Url::create('/foo'), - Url::create('/bar'), - Url::create('/baz'), + Url::create('https://example.com/foo'), + Url::create('https://example.com/bar'), + Url::create('https://example.com/baz'), ]; $this->expected_buffer .= self::OPENED; @@ -165,7 +165,7 @@ public function testPush(): void public function testOverflowLinks(): void { - $url = Url::create('/'); + $url = Url::create('https://example.com/'); $this->stream->open(); $this->render ->expects(self::atLeastOnce()) @@ -185,9 +185,10 @@ public function testOverflowSize(): void { $loops = (int) floor(Limiter::BYTE_LIMIT / Location::MAX_LENGTH); $prefix_size = Limiter::BYTE_LIMIT - ($loops * Location::MAX_LENGTH); - $opened = str_repeat('/', $prefix_size); - $location = str_repeat('/', Location::MAX_LENGTH); - $closed = '/'; // overflow byte + $opened = str_repeat('<', $prefix_size); + $location = 'https://example.com/'; + $location .= str_repeat('f', Location::MAX_LENGTH - strlen($location)); + $closed = '>'; // overflow byte $url = Url::create($location); $this->render diff --git a/tests/Stream/WritingIndexStreamTest.php b/tests/Stream/WritingIndexStreamTest.php index bea7dc9..e51ebe1 100644 --- a/tests/Stream/WritingIndexStreamTest.php +++ b/tests/Stream/WritingIndexStreamTest.php @@ -115,7 +115,7 @@ public function testCloseAlreadyClosed(): void public function testPushNotOpened(): void { $this->expectException(StreamStateException::class); - $this->stream->pushSitemap(new Sitemap('/sitemap_news.xml')); + $this->stream->pushSitemap(new Sitemap('https://example.com/sitemap_news.xml')); } public function testPushAfterClosed(): void @@ -124,15 +124,15 @@ public function testPushAfterClosed(): void $this->stream->close(); $this->expectException(StreamStateException::class); - $this->stream->pushSitemap(new Sitemap('/sitemap_news.xml')); + $this->stream->pushSitemap(new Sitemap('https://example.com/sitemap_news.xml')); } public function testPush(): void { $sitemaps = [ - new Sitemap('/sitemap_foo.xml'), - new Sitemap('/sitemap_bar.xml'), - new Sitemap('/sitemap_baz.xml'), + new Sitemap('https://example.com/sitemap_foo.xml'), + new Sitemap('https://example.com/sitemap_bar.xml'), + new Sitemap('https://example.com/sitemap_baz.xml'), ]; // build expects @@ -152,7 +152,7 @@ public function testPush(): void public function testOverflowLinks(): void { - $sitemap = new Sitemap('/sitemap_news.xml'); + $sitemap = new Sitemap('https://example.com/sitemap_news.xml'); $this->stream->open(); diff --git a/tests/Stream/WritingSplitIndexStreamTest.php b/tests/Stream/WritingSplitIndexStreamTest.php index 60872cb..701229e 100644 --- a/tests/Stream/WritingSplitIndexStreamTest.php +++ b/tests/Stream/WritingSplitIndexStreamTest.php @@ -77,7 +77,7 @@ final class WritingSplitIndexStreamTest extends TestCase /** * @var string */ - private const PART_WEB_PATH = '/sitemap%d.xml.gz'; + private const PART_WEB_PATH = 'https://example.com/sitemap%d.xml.gz'; /** * @var MockObject&SitemapIndexRender @@ -153,7 +153,9 @@ protected function setUp(): void $this->part_render, $this->index_writer, $this->part_writer, - self::INDEX_PATH + self::INDEX_PATH, + self::PART_PATH, + self::PART_WEB_PATH ); } @@ -201,13 +203,13 @@ public function testCloseAlreadyClosed(): void public function testPushNotOpened(): void { $this->expectException(StreamStateException::class); - $this->stream->push(Url::create('/')); + $this->stream->push(Url::create('https://example.com/')); } public function testPushSitemapNotOpened(): void { $this->expectException(StreamStateException::class); - $this->stream->pushSitemap(new Sitemap('/sitemap_news.xml')); + $this->stream->pushSitemap(new Sitemap('https://example.com/sitemap_news.xml')); } public function testPushAfterClosed(): void @@ -221,7 +223,7 @@ public function testPushAfterClosed(): void $this->stream->close(); $this->expectException(StreamStateException::class); - $this->stream->push(Url::create('/')); + $this->stream->push(Url::create('https://example.com/')); } public function testEmptyIndex(): void @@ -240,45 +242,6 @@ public function testEmptyIndex(): void $this->stream->close(); } - /** - * @return string[][] - */ - public function getPartFilenames(): array - { - return [ - ['sitemap.xml', 'sitemap1.xml'], - ['sitemap.xml.gz', 'sitemap1.xml.gz'], // custom filename extension - ['sitemap_part.xml', 'sitemap_part1.xml'], // custom filename - ['/sitemap.xml', '/sitemap1.xml'], // in root folder - ['/var/www/sitemap.xml', '/var/www/sitemap1.xml'], // in folder - ]; - } - - /** - * @dataProvider getPartFilenames - * - * @param string $index_filename - * @param string $part_filename - */ - public function testPartFilenames(string $index_filename, string $part_filename): void - { - $this->expectOpen($index_filename); - $this->expectOpenPart($part_filename); - $this->expectClosePart(); - $this->expectClose(); - - $this->stream = new WritingSplitIndexStream( - $this->index_render, - $this->part_render, - $this->index_writer, - $this->part_writer, - $index_filename - ); - - $this->stream->open(); - $this->stream->close(); - } - /** * @return string[][] */ @@ -342,12 +305,13 @@ public function testConflictWriters(): void $this->tmp_part_filename = $this->tempnam(sys_get_temp_dir(), 's%d'); $stream = new WritingSplitIndexStream( - new PlainTextSitemapIndexRender('https://example.com'), - new PlainTextSitemapRender('https://example.com'), + new PlainTextSitemapIndexRender(), + new PlainTextSitemapRender(), $writer, $writer, $this->tmp_index_filename, - $this->tmp_part_filename + $this->tmp_part_filename, + self::PART_WEB_PATH ); $stream->open(); @@ -357,9 +321,9 @@ public function testConflictWriters(): void public function testPush(): void { $urls = [ - Url::create('/foo'), - Url::create('/bar'), - Url::create('/baz'), + Url::create('https://example.com/foo'), + Url::create('https://example.com/bar'), + Url::create('https://example.com/baz'), ]; $this->expectOpen(); @@ -401,7 +365,7 @@ public function testPush(): void public function testSplitOverflowLinks(): void { - $url = Url::create('/'); + $url = Url::create('https://example.com/'); $this->expectOpen(); $this->expectOpenPart(); @@ -473,13 +437,13 @@ public function testSplitOverflowLinks(): void public function testSplitOverflowSize(): void { - $url = Url::create('/'); + $url = Url::create('https://example.com/'); $loops = 10000; $loop_size = (int) floor(Limiter::BYTE_LIMIT / $loops); $prefix_size = Limiter::BYTE_LIMIT - ($loops * $loop_size); $url_tpl = str_repeat('/', $loop_size); - $open = str_repeat('/', $prefix_size); - $close = '/'; // overflow byte + $open = str_repeat('<', $prefix_size); + $close = '>'; // overflow byte $this->expectOpen(); $this->expectOpenPart('', $open, $close); @@ -564,7 +528,7 @@ public function testOverflow(): void // $this->expectOpen(); // $this->expectOpenPart(); // -// $url = Url::create('/foo'); +// $url = Url::create('https://example.com/foo'); // $this->stream->open(); // for ($i = 0; $i <= Limiter::SITEMAPS_LIMIT * Limiter::LINKS_LIMIT; ++$i) { // $this->stream->push($url); @@ -573,7 +537,7 @@ public function testOverflow(): void public function testPushSitemap(): void { - $sitemap = new Sitemap('/sitemap_news.xml'); + $sitemap = new Sitemap('https://example.com/sitemap_news.xml'); $this->expectOpen(); $this->expectOpenPart(); @@ -605,7 +569,7 @@ public function testPushSitemapOverflow(): void $this->expectOpen(); $this->expectOpenPart(); - $sitemap = new Sitemap('/sitemap_news.xml'); + $sitemap = new Sitemap('https://example.com/sitemap_news.xml'); $this->stream->open(); for ($i = 0; $i <= Limiter::SITEMAPS_LIMIT; ++$i) { $this->stream->pushSitemap($sitemap); diff --git a/tests/Stream/WritingSplitStreamTest.php b/tests/Stream/WritingSplitStreamTest.php index d05f6df..8c94357 100644 --- a/tests/Stream/WritingSplitStreamTest.php +++ b/tests/Stream/WritingSplitStreamTest.php @@ -42,7 +42,7 @@ final class WritingSplitStreamTest extends TestCase /** * @var string */ - private const WEB_PATH = '/sitemap%d.xml.gz'; + private const WEB_PATH = 'https://example.com/sitemap%d.xml.gz'; /** * @var MockObject&SitemapRender @@ -75,7 +75,7 @@ protected function setUp(): void $this->write_call = 0; $this->render = $this->createMock(SitemapRender::class); $this->writer = $this->createMock(Writer::class); - $this->stream = new WritingSplitStream($this->render, $this->writer, self::FILENAME); + $this->stream = new WritingSplitStream($this->render, $this->writer, self::FILENAME, self::WEB_PATH); } public function testOpenClose(): void @@ -122,7 +122,7 @@ public function testCloseAlreadyClosed(): void public function testPushNotOpened(): void { $this->expectException(StreamStateException::class); - $this->stream->push(Url::create('/')); + $this->stream->push(Url::create('https://example.com/')); } public function testPushAfterClosed(): void @@ -131,15 +131,15 @@ public function testPushAfterClosed(): void $this->stream->close(); $this->expectException(StreamStateException::class); - $this->stream->push(Url::create('/')); + $this->stream->push(Url::create('https://example.com/')); } public function testPush(): void { $urls = [ - Url::create('/foo'), - Url::create('/bar'), - Url::create('/baz'), + Url::create('https://example.com/foo'), + Url::create('https://example.com/bar'), + Url::create('https://example.com/baz'), ]; // build expects @@ -206,7 +206,7 @@ public function testGetEmptySitemapsList(): void public function testGetSitemaps(): void { - $url = Url::create('/'); + $url = Url::create('https://example.com/'); $now = time(); $this->expectOpen(); @@ -233,7 +233,7 @@ public function testGetSitemaps(): void public function testSplitOverflowLinks(): void { - $url = Url::create('/'); + $url = Url::create('https://example.com/'); $now = time(); $overflow = 10; @@ -294,9 +294,10 @@ public function testSplitOverflowSize(): void { $loops = (int) floor(Limiter::BYTE_LIMIT / Location::MAX_LENGTH); $prefix_size = Limiter::BYTE_LIMIT - ($loops * Location::MAX_LENGTH); - $opened = str_repeat('/', $prefix_size); - $location = str_repeat('/', Location::MAX_LENGTH); - $closed = '/'; // overflow byte + $opened = str_repeat('<', $prefix_size); + $location = 'https://example.com/'; + $location .= str_repeat('f', Location::MAX_LENGTH - strlen($location)); + $closed = '>'; // overflow byte $url = Url::create($location); $now = time(); diff --git a/tests/Stream/WritingStreamTest.php b/tests/Stream/WritingStreamTest.php index d8021a0..19173cd 100644 --- a/tests/Stream/WritingStreamTest.php +++ b/tests/Stream/WritingStreamTest.php @@ -117,7 +117,7 @@ public function testCloseAlreadyClosed(): void public function testPushNotOpened(): void { $this->expectException(StreamStateException::class); - $this->stream->push(Url::create('/')); + $this->stream->push(Url::create('https://example.com/')); } public function testPushAfterClosed(): void @@ -126,15 +126,15 @@ public function testPushAfterClosed(): void $this->stream->close(); $this->expectException(StreamStateException::class); - $this->stream->push(Url::create('/')); + $this->stream->push(Url::create('https://example.com/')); } public function testPush(): void { $urls = [ - Url::create('/foo'), - Url::create('/bar'), - Url::create('/baz'), + Url::create('https://example.com/foo'), + Url::create('https://example.com/bar'), + Url::create('https://example.com/baz'), ]; // build expects @@ -154,7 +154,7 @@ public function testPush(): void public function testOverflowLinks(): void { - $url = Url::create('/'); + $url = Url::create('https://example.com/'); $this->stream->open(); @@ -170,9 +170,10 @@ public function testOverflowSize(): void { $loops = (int) floor(Limiter::BYTE_LIMIT / Location::MAX_LENGTH); $prefix_size = Limiter::BYTE_LIMIT - ($loops * Location::MAX_LENGTH); - $opened = str_repeat('/', $prefix_size); - $location = str_repeat('/', Location::MAX_LENGTH); - $closed = '/'; // overflow byte + $opened = str_repeat('<', $prefix_size); + $location = 'https://example.com/'; + $location .= str_repeat('f', Location::MAX_LENGTH - strlen($location)); + $closed = '>'; // overflow byte $url = Url::create($location); diff --git a/tests/Url/LanguageTest.php b/tests/Url/LanguageTest.php index 305e509..13a5316 100644 --- a/tests/Url/LanguageTest.php +++ b/tests/Url/LanguageTest.php @@ -44,7 +44,7 @@ public function testInvalidLanguages(string $language): void { $this->expectException(InvalidLanguageException::class); - new Language($language, ''); + new Language($language, 'https://example.com'); } /** @@ -53,9 +53,13 @@ public function testInvalidLanguages(string $language): void public function getInvalidLocations(): array { return [ + [''], + ['/'], ['../'], ['index.html'], + ['?foo=bar'], ['&foo=bar'], + ['#'], ['№'], ['@'], ['\\'], @@ -82,17 +86,13 @@ public function getLanguage(): array $result = []; $languages = ['x-default']; $locations = [ - '', - '/', - '#about', - '?foo=bar', - '?foo=bar&baz=123', - '/index.html', - '/about/index.html', - ]; - $web_paths = [ 'https://example.com', - 'http://example.org/catalog', + 'https://example.com/', + 'https://example.com#about', + 'https://example.com?foo=bar', + 'https://example.com?foo=bar&baz=123', + 'https://example.com/index.html', + 'https://example.com/about/index.html', ]; // build list $languages @@ -113,15 +113,6 @@ public function getLanguage(): array } } - // build remote locations - foreach ($web_paths as $web_path) { - foreach ($locations as $location) { - foreach ($languages as $language) { - $result[] = [$language, $web_path.$location, false]; - } - } - } - return $result; } @@ -130,18 +121,11 @@ public function getLanguage(): array * * @param string $language * @param string $location - * @param bool $local */ - public function testLanguage(string $language, string $location, bool $local): void + public function testLanguage(string $language, string $location): void { $lang = new Language($language, $location); self::assertSame($language, $lang->getLanguage()); - self::assertSame($location, $lang->getLocation()); - - if ($local) { - self::assertTrue($lang->isLocalLocation()); - } else { - self::assertFalse($lang->isLocalLocation()); - } + self::assertSame($location, (string) $lang->getLocation()); } } diff --git a/tests/Url/PriorityTest.php b/tests/Url/PriorityTest.php index 43980d9..417bb86 100644 --- a/tests/Url/PriorityTest.php +++ b/tests/Url/PriorityTest.php @@ -108,19 +108,19 @@ public function testInvalid($priority): void public function getPriorityOfLocations(): array { return [ - ['/', '1.0'], - ['/index.html', '0.9'], - ['/catalog', '0.9'], - ['/catalog/123', '0.8'], - ['/catalog/123/article', '0.7'], - ['/catalog/123/article/456', '0.6'], - ['/catalog/123/article/456/print', '0.5'], - ['/catalog/123/subcatalog/789/article/456', '0.4'], - ['/catalog/123/subcatalog/789/article/456/print', '0.3'], - ['/catalog/123/subcatalog/789/article/456/print/foo', '0.2'], - ['/catalog/123/subcatalog/789/article/456/print/foo/bar', '0.1'], - ['/catalog/123/subcatalog/789/article/456/print/foo/bar/baz', '0.1'], - ['/catalog/123/subcatalog/789/article/456/print/foo/bar/baz/qux', '0.1'], + ['https://example.com/', '1.0'], + ['https://example.com/index.html', '0.9'], + ['https://example.com/catalog', '0.9'], + ['https://example.com/catalog/123', '0.8'], + ['https://example.com/catalog/123/article', '0.7'], + ['https://example.com/catalog/123/article/456', '0.6'], + ['https://example.com/catalog/123/article/456/print', '0.5'], + ['https://example.com/catalog/123/subcatalog/789/article/456', '0.4'], + ['https://example.com/catalog/123/subcatalog/789/article/456/print', '0.3'], + ['https://example.com/catalog/123/subcatalog/789/article/456/print/foo', '0.2'], + ['https://example.com/catalog/123/subcatalog/789/article/456/print/foo/bar', '0.1'], + ['https://example.com/catalog/123/subcatalog/789/article/456/print/foo/bar/baz', '0.1'], + ['https://example.com/catalog/123/subcatalog/789/article/456/print/foo/bar/baz/qux', '0.1'], ]; } diff --git a/tests/Url/UrlTest.php b/tests/Url/UrlTest.php index e21bd51..049f61e 100644 --- a/tests/Url/UrlTest.php +++ b/tests/Url/UrlTest.php @@ -25,7 +25,7 @@ final class UrlTest extends TestCase { public function testDefaultUrl(): void { - $location = ''; + $location = 'https://example.com'; $url = Url::create($location); self::assertEquals($location, (string) $url->getLocation()); @@ -37,7 +37,7 @@ public function testDefaultUrl(): void public function testDefaultSmartUrl(): void { - $location = ''; + $location = 'https://example.com'; $url = Url::createSmart($location); $priority = Priority::createByLocation(new Location($location)); @@ -81,7 +81,7 @@ public function getUrls(): array */ public function testCustomUrl(\DateTimeInterface $last_modify, string $change_frequency, string $priority): void { - $location = '/index.html'; + $location = 'https://example.com/index.html'; $url = Url::create($location, $last_modify, $change_frequency, $priority); @@ -103,7 +103,7 @@ public function testCustomSmartUrl( string $change_frequency, string $priority ): void { - $location = '/index.html'; + $location = 'https://example.com/index.html'; $url = Url::createSmart($location, $last_modify, $change_frequency, $priority); @@ -119,9 +119,13 @@ public function testCustomSmartUrl( public function getInvalidLocations(): array { return [ + [''], + ['/'], ['../'], ['index.html'], + ['?foo=bar'], ['&foo=bar'], + ['#'], ['№'], ['@'], ['\\'], @@ -158,13 +162,13 @@ public function testInvalidSmartLocation(string $location): void public function getValidLocations(): array { return [ - [''], - ['/'], - ['#about'], - ['?foo=bar'], - ['?foo=bar&baz=123'], - ['/index.html'], - ['/about/index.html'], + ['https://example.com'], + ['https://example.com/'], + ['https://example.com#about'], + ['https://example.com?foo=bar'], + ['https://example.com?foo=bar&baz=123'], + ['https://example.com/index.html'], + ['https://example.com/about/index.html'], ]; } @@ -192,53 +196,53 @@ public function testInvalidLastModify(): void { $this->expectException(InvalidLastModifyException::class); - Url::create('/', new \DateTimeImmutable('+1 minutes')); + Url::create('https://example.com/', new \DateTimeImmutable('+1 minutes')); } public function testInvalidSmartLastModify(): void { $this->expectException(InvalidLastModifyException::class); - Url::createSmart('/', new \DateTimeImmutable('+1 minutes')); + Url::createSmart('https://example.com/', new \DateTimeImmutable('+1 minutes')); } public function testInvalidPriority(): void { $this->expectException(InvalidPriorityException::class); - Url::create('/', null, null, 11); + Url::create('https://example.com/', null, null, 11); } public function testInvalidSmartPriority(): void { $this->expectException(InvalidPriorityException::class); - Url::createSmart('/', null, null, 11); + Url::createSmart('https://example.com/', null, null, 11); } public function testInvalidChangeFrequency(): void { $this->expectException(InvalidChangeFrequencyException::class); - Url::create('/', null, ''); + Url::create('https://example.com/', null, ''); } public function testInvalidSmartChangeFrequency(): void { $this->expectException(InvalidChangeFrequencyException::class); - Url::createSmart('/', null, ''); + Url::createSmart('https://example.com/', null, ''); } public function testGetLanguages(): void { $languages = [ - 'de' => '/deutsch/page.html', - 'de-ch' => '/schweiz-deutsch/page.html', - 'en' => '/english/page.html', + 'de' => 'https://example.com/deutsch/page.html', + 'de-ch' => 'https://example.com/schweiz-deutsch/page.html', + 'en' => 'https://example.com/english/page.html', ]; - $url = Url::create('/english/page.html', null, null, null, $languages); + $url = Url::create('https://example.com/english/page.html', null, null, null, $languages); self::assertNotEmpty($url->getLanguages()); @@ -247,19 +251,19 @@ public function testGetLanguages(): void foreach ($url->getLanguages() as $j => $language) { self::assertInstanceOf(Language::class, $language); self::assertSame($keys[$j], $language->getLanguage()); - self::assertSame($languages[$keys[$j]], $language->getLocation()); + self::assertSame($languages[$keys[$j]], (string) $language->getLocation()); } } public function testGetSmartLanguages(): void { $languages = [ - 'de' => '/deutsch/page.html', - 'de-ch' => '/schweiz-deutsch/page.html', - 'en' => '/english/page.html', + 'de' => 'https://example.com/deutsch/page.html', + 'de-ch' => 'https://example.com/schweiz-deutsch/page.html', + 'en' => 'https://example.com/english/page.html', ]; - $url = Url::createSmart('/english/page.html', null, null, null, $languages); + $url = Url::createSmart('https://example.com/english/page.html', null, null, null, $languages); self::assertNotEmpty($url->getLanguages()); @@ -268,7 +272,7 @@ public function testGetSmartLanguages(): void foreach ($url->getLanguages() as $j => $language) { self::assertInstanceOf(Language::class, $language); self::assertSame($keys[$j], $language->getLanguage()); - self::assertSame($languages[$keys[$j]], $language->getLocation()); + self::assertSame($languages[$keys[$j]], (string) $language->getLocation()); } } @@ -285,9 +289,9 @@ public function testCreateLanguageUrls( string $priority ): void { $languages = [ - 'de' => '/deutsch/page.html', - 'de-ch' => '/schweiz-deutsch/page.html', - 'en' => '/english/page.html', + 'de' => 'https://example.com/deutsch/page.html', + 'de-ch' => 'https://example.com/schweiz-deutsch/page.html', + 'en' => 'https://example.com/english/page.html', ]; $external_languages = [ 'de' => 'https://example.de', // should be overwritten from $languages @@ -311,7 +315,7 @@ public function testCreateLanguageUrls( foreach ($url->getLanguages() as $j => $language) { self::assertInstanceOf(Language::class, $language); self::assertSame($keys[$j], $language->getLanguage()); - self::assertSame($expected_languages[$keys[$j]], $language->getLocation()); + self::assertSame($expected_languages[$keys[$j]], (string) $language->getLocation()); } } } @@ -324,41 +328,41 @@ public function getNonUniqueLanguageLocations(): array return [ [ [ - 'de' => '/deutsch/page.html', - 'de-ch' => '/schweiz-deutsch/page.html', - 'en' => '/english/page.html', - 'x-default' => '/english/page.html', + 'de' => 'https://example.com/deutsch/page.html', + 'de-ch' => 'https://example.com/schweiz-deutsch/page.html', + 'en' => 'https://example.com/english/page.html', + 'x-default' => 'https://example.com/english/page.html', ], [ - '/deutsch/page.html', - '/schweiz-deutsch/page.html', - '/english/page.html', + 'https://example.com/deutsch/page.html', + 'https://example.com/schweiz-deutsch/page.html', + 'https://example.com/english/page.html', ], ], [ [ - 'de' => '/deutsch/page.html', - 'de-ch' => '/schweiz-deutsch/page.html', - 'x-default' => '/english/page.html', // unmatched language + 'de' => 'https://example.com/deutsch/page.html', + 'de-ch' => 'https://example.com/schweiz-deutsch/page.html', + 'x-default' => 'https://example.com/english/page.html', // unmatched language ], [ - '/deutsch/page.html', - '/schweiz-deutsch/page.html', - '/english/page.html', + 'https://example.com/deutsch/page.html', + 'https://example.com/schweiz-deutsch/page.html', + 'https://example.com/english/page.html', ], ], [ [ - 'de' => '/deutsch/page.html', - 'de-ch' => '/schweiz-deutsch/page.html', - 'en' => '/english/page.html', - 'en-US' => '/english/page.html', - 'en-GB' => '/english/page.html', + 'de' => 'https://example.com/deutsch/page.html', + 'de-ch' => 'https://example.com/schweiz-deutsch/page.html', + 'en' => 'https://example.com/english/page.html', + 'en-US' => 'https://example.com/english/page.html', + 'en-GB' => 'https://example.com/english/page.html', ], [ - '/deutsch/page.html', - '/schweiz-deutsch/page.html', - '/english/page.html', + 'https://example.com/deutsch/page.html', + 'https://example.com/schweiz-deutsch/page.html', + 'https://example.com/english/page.html', ], ], ]; @@ -384,7 +388,7 @@ public function testCreateLanguageUrlsUnique(array $languages, array $locations) foreach ($url->getLanguages() as $j => $language) { self::assertInstanceOf(Language::class, $language); self::assertSame($keys[$j], $language->getLanguage()); - self::assertSame($languages[$keys[$j]], $language->getLocation()); + self::assertSame($languages[$keys[$j]], (string) $language->getLocation()); } } } @@ -395,19 +399,19 @@ public function testCreateLanguageUrlsUnique(array $languages, array $locations) public function getPriorityOfLocations(): array { return [ - ['/', '1.0'], - ['/index.html', '0.9'], - ['/catalog', '0.9'], - ['/catalog/123', '0.8'], - ['/catalog/123/article', '0.7'], - ['/catalog/123/article/456', '0.6'], - ['/catalog/123/article/456/print', '0.5'], - ['/catalog/123/subcatalog/789/article/456', '0.4'], - ['/catalog/123/subcatalog/789/article/456/print', '0.3'], - ['/catalog/123/subcatalog/789/article/456/print/foo', '0.2'], - ['/catalog/123/subcatalog/789/article/456/print/foo/bar', '0.1'], - ['/catalog/123/subcatalog/789/article/456/print/foo/bar/baz', '0.1'], - ['/catalog/123/subcatalog/789/article/456/print/foo/bar/baz/qux', '0.1'], + ['https://example.com/', '1.0'], + ['https://example.com/index.html', '0.9'], + ['https://example.com/catalog', '0.9'], + ['https://example.com/catalog/123', '0.8'], + ['https://example.com/catalog/123/article', '0.7'], + ['https://example.com/catalog/123/article/456', '0.6'], + ['https://example.com/catalog/123/article/456/print', '0.5'], + ['https://example.com/catalog/123/subcatalog/789/article/456', '0.4'], + ['https://example.com/catalog/123/subcatalog/789/article/456/print', '0.3'], + ['https://example.com/catalog/123/subcatalog/789/article/456/print/foo', '0.2'], + ['https://example.com/catalog/123/subcatalog/789/article/456/print/foo/bar', '0.1'], + ['https://example.com/catalog/123/subcatalog/789/article/456/print/foo/bar/baz', '0.1'], + ['https://example.com/catalog/123/subcatalog/789/article/456/print/foo/bar/baz/qux', '0.1'], ]; } @@ -452,7 +456,7 @@ public function testSmartChangeFrequencyFromLastMod( \DateTimeInterface $last_modify, string $change_frequency ): void { - $location = '/'; + $location = 'https://example.com/'; $url = Url::createSmart($location, $last_modify); self::assertEquals($location, (string) $url->getLocation()); @@ -488,7 +492,7 @@ public function getChangeFrequencyOfPriority(): array */ public function testSmartChangeFrequencyFromPriority(string $priority, string $change_frequency): void { - $location = '/'; + $location = 'https://example.com/'; $url = Url::createSmart($location, null, null, $priority); self::assertEquals($location, (string) $url->getLocation());