"GALETTE_CONFIG_PATH",
"GALETTE_DATA_PATH",
"GALETTE_DB_VERSION",
+ "GALETTE_DOWNLOADS_URI",
"GALETTE_EXPORTS_PATH",
"GALETTE_FILES_PATH",
"GALETTE_IMPORTS_PATH",
"twig/twig": "^3.3",
"slim/twig-view": "^3.3",
"slim/psr7": "^1.6",
- "symfony/yaml": "^6.2"
+ "symfony/yaml": "^6.2",
+ "guzzlehttp/guzzle": "^7.8"
},
"require-dev": {
"squizlabs/php_codesniffer": "^3.7",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "d9d666c177b29251a86016612325d3ca",
+ "content-hash": "dbbf63121881c53f2c16c57ee40027ed",
"packages": [
{
"name": "akrabat/rka-slim-session-middleware",
},
"time": "2020-11-24T22:02:12+00:00"
},
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "7.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "41042bc7ab002487b876a0683fc8dce04ddce104"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104",
+ "reference": "41042bc7ab002487b876a0683fc8dce04ddce104",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "guzzlehttp/promises": "^1.5.3 || ^2.0.1",
+ "guzzlehttp/psr7": "^1.9.1 || ^2.5.1",
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-client": "^1.0",
+ "symfony/deprecation-contracts": "^2.2 || ^3.0"
+ },
+ "provide": {
+ "psr/http-client-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "ext-curl": "*",
+ "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999",
+ "php-http/message-factory": "^1.1",
+ "phpunit/phpunit": "^8.5.36 || ^9.6.15",
+ "psr/log": "^1.1 || ^2.0 || ^3.0"
+ },
+ "suggest": {
+ "ext-curl": "Required for CURL handler support",
+ "ext-intl": "Required for Internationalized Domain Name (IDN) support",
+ "psr/log": "Required for using the Log middleware"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Jeremy Lindblom",
+ "email": "jeremeamia@gmail.com",
+ "homepage": "https://github.com/jeremeamia"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "psr-18",
+ "psr-7",
+ "rest",
+ "web service"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/guzzle/issues",
+ "source": "https://github.com/guzzle/guzzle/tree/7.8.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-12-03T20:35:24+00:00"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223",
+ "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "phpunit/phpunit": "^8.5.36 || ^9.6.15"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/promises/issues",
+ "source": "https://github.com/guzzle/promises/tree/2.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-12-03T20:19:20+00:00"
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "2.6.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221",
+ "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-factory": "^1.0",
+ "psr/http-message": "^1.1 || ^2.0",
+ "ralouphie/getallheaders": "^3.0"
+ },
+ "provide": {
+ "psr/http-factory-implementation": "1.0",
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "http-interop/http-factory-tests": "^0.9",
+ "phpunit/phpunit": "^8.5.36 || ^9.6.15"
+ },
+ "suggest": {
+ "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://sagikazarmark.hu"
+ }
+ ],
+ "description": "PSR-7 message implementation that also provides common utility methods",
+ "keywords": [
+ "http",
+ "message",
+ "psr-7",
+ "request",
+ "response",
+ "stream",
+ "uri",
+ "url"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/psr7/issues",
+ "source": "https://github.com/guzzle/psr7/tree/2.6.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-12-03T20:05:35+00:00"
+ },
{
"name": "laminas/laminas-db",
"version": "2.18.0",
},
"time": "2019-01-08T18:20:26+00:00"
},
+ {
+ "name": "psr/http-client",
+ "version": "1.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-client.git",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Client\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP clients",
+ "homepage": "https://github.com/php-fig/http-client",
+ "keywords": [
+ "http",
+ "http-client",
+ "psr",
+ "psr-18"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-client"
+ },
+ "time": "2023-09-23T14:17:50+00:00"
+ },
{
"name": "psr/http-factory",
"version": "1.0.2",
if (!defined('GALETTE_TPL_THEME_DIR')) {
define('GALETTE_TPL_THEME_DIR', GALETTE_ROOT . 'templates/default/');
}
+
+if (!defined('GALETTE_DOWNLOADS_URI')) {
+ define('GALETTE_DOWNLOADS_URI', 'https://download.tuxfamily.org/galette/');
+}
* along with Galette. If not, see <http://www.gnu.org/licenses/>.
*/
+use Analog\Analog;
use Galette\Middleware\Authenticate;
use Galette\Middleware\Language;
use Galette\Middleware\Telemetry;
use Galette\Middleware\TrailingSlash;
use Galette\Middleware\UpdateAndMaintenance;
+use Galette\Util\Release;
use RKA\SessionMiddleware;
use Slim\Routing\RouteContext;
use Galette\Core\Galette;
//Telemetry update middleware
$app->add(Telemetry::class);
+//check for new release
+if (
+ $container->get('login')->isSuperAdmin()
+ || $container->get('login')->isAdmin()
+ || $container->get('login')->isStaff()
+) {
+ try {
+ $release = new Release();
+ if ($release->checkNewRelease()) {
+ Analog::log(
+ sprintf(
+ 'A new Galette release is available: %s (current %s)',
+ $release->getLatestRelease(),
+ GALETTE_VERSION
+ ),
+ Analog::INFO
+ );
+ $container->get('flash')->addMessage(
+ 'info',
+ [
+ 'title' => _T('A new Galette release is available.'),
+ 'message' => sprintf(
+ _T('You currently use Galette %1$s, and %2$s is available.'),
+ GALETTE_VERSION,
+ $release->getLatestRelease()
+ )
+ ]
+ );
+ }
+ } catch (\Throwable $e) {
+ Analog::log(
+ 'Error looking for new release: ' . $e->getMessage(),
+ Analog::ERROR
+ );
+ }
+}
+
require_once GALETTE_ROOT . 'includes/routes/authentication.routes.php';
require_once GALETTE_ROOT . 'includes/routes/management.routes.php';
require_once GALETTE_ROOT . 'includes/routes/members.routes.php';
--- /dev/null
+<?php
+
+/**
+ * Copyright © 2003-2024 The Galette Team
+ *
+ * This file is part of Galette (https://galette.eu).
+ *
+ * Galette is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Galette is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Galette. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace Galette\Util;
+
+use GuzzleHttp\Client;
+
+/**
+ * Check for new Galette release
+ *
+ * @author Johan Cwiklinski <johan@x-tnd.be>
+ */
+class Release
+{
+ /** @var array<string, mixed> */
+ private array $default_options = [
+ 'timeout' => 2.0,
+ ];
+ private ?string $latest = null;
+
+ /**
+ * Set ups Guzzle client
+ *
+ * @return Client
+ */
+ public function setupClient(): Client
+ {
+ $this->client = new Client(
+ $this->getDefaultOptions()
+ );
+ return $this->client;
+ }
+
+ /**
+ * Get default options
+ *
+ * @return array<string, mixed>
+ */
+ public function getDefaultOptions(): array
+ {
+ return $this->default_options;
+ }
+
+ /**
+ * Get the latest release
+ *
+ * @return ?string
+ */
+ public function getLatestRelease(): ?string
+ {
+ if (!isset($this->latest)) {
+ $this->latest = $this->findLatestRelease();
+ }
+ return $this->latest;
+ }
+
+ /**
+ * Get the latest release
+ *
+ * @return ?string
+ */
+ public function findLatestRelease(): ?string
+ {
+ if (isset($this->latest)) {
+ return $this->getLatestRelease();
+ }
+
+ $client = $this->setupClient();
+ $response = $client->request('GET', $this->getReleasesURL());
+ $contents = $response->getBody()->getContents();
+
+ $releases = [];
+ preg_match_all(
+ '/href="(galette-.[^"]+\.tar\.bz2)"/',
+ $contents,
+ $releases
+ );
+
+ $latest = null;
+ foreach ($releases[1] as $release) {
+ $release = str_replace('galette-', '', $release);
+ $release = str_replace('.tar.bz2', '', $release);
+ if ($release === 'dev') {
+ continue;
+ }
+ if (version_compare($release, $latest ?? 0, '>')) {
+ $latest = $release;
+ }
+ }
+
+ return $latest;
+ }
+
+ /**
+ * Check if a new release is available
+ *
+ * @return bool
+ */
+ public function checkNewRelease(): bool
+ {
+ $current = $this->getCurrentRelease();
+ if (str_ends_with($current, '-dev')) {
+ //current version is a dev version
+ return false;
+ }
+
+ $this->latest = $this->getLatestRelease();
+ if ($this->latest === null) {
+ return false;
+ }
+
+ return version_compare($this->latest, ltrim($this->getCurrentRelease(), 'v'), '>');
+ }
+
+ /**
+ * Get the current release
+ *
+ * @return string
+ */
+ public function getCurrentRelease(): string
+ {
+ return GALETTE_VERSION;
+ }
+
+ /**
+ * Get the URL to download releases
+ *
+ * @return string
+ */
+ public function getReleasesURL(): string
+ {
+ return GALETTE_DOWNLOADS_URI;
+ }
+}
--- /dev/null
+<?php
+
+/**
+ * Copyright © 2003-2024 The Galette Team
+ *
+ * This file is part of Galette (https://galette.eu).
+ *
+ * Galette is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Galette is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Galette. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace Galette\Util\test\units;
+
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Release tests class
+ *
+ * @author Johan Cwiklinski <johan@x-tnd.be>
+ */
+class Release extends TestCase
+{
+ /**
+ * Releases provider
+ *
+ * @return array<int, array<int, string|bool>>
+ */
+ public static function releasesProvider(): array
+ {
+ return [
+ ['0.7.0', '1.1.0', true],
+ ['1.0.0', '1.1.0', true],
+ ['1.0.1', '1.1.0', true],
+ ['1.1.0', '1.1.0', false],
+ ['1.2.0', '1.1.0', false],
+ ];
+ }
+
+ /**
+ * Test checkNewRelease
+ *
+ * @param string $current Current release
+ * @param string $latest Latest release
+ * @param bool $expected Expected result
+ *
+ * @dataProvider releasesProvider
+ * @return void
+ */
+ public function testNewRelease(string $current, string $latest, bool $expected): void
+ {
+ $release = $this->getMockBuilder(\Galette\Util\Release::class)
+ ->onlyMethods(array('getCurrentRelease', 'getLatestRelease'))
+ ->getMock();
+
+ $release->method('getCurrentRelease')->willReturn($current);
+ $release->method('getLatestRelease')->willReturn($latest);
+
+ $this->assertSame($expected, $release->checkNewRelease());
+ }
+
+ /**
+ * Releases provider
+ *
+ * @return array<int, array<int, string|bool>>
+ */
+ public static function releasesPageProvider(): array
+ {
+ return [
+ [
+ '0.7.0',
+ '1.0.2',
+ true,
+ '<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<title>Index of /galette/</title>
+<style type="text/css">
+a, a:active {text-decoration: none; color: blue;}
+a:visited {color: #48468F;}
+a:hover, a:focus {text-decoration: underline; color: red;}
+body {background-color: #F5F5F5;}
+h2 {margin-bottom: 12px;}
+table {margin-left: 12px;}
+th, td { font: 90% monospace; text-align: left;}
+th { font-weight: bold; padding-right: 14px; padding-bottom: 3px;}
+td {padding-right: 14px;}
+td.s, th.s {text-align: right;}
+div.list { background-color: white; border-top: 1px solid #646464; border-bottom: 1px solid #646464; padding-top: 10px; padding-bottom: 14px;}
+div.foot { font: 90% monospace; color: #787878; padding-top: 4px;}
+</style>
+</head>
+<body>
+<h2>Index of /galette/</h2>
+<div class="list">
+<table summary="Directory Listing" cellpadding="0" cellspacing="0">
+<thead><tr><th class="n">Name</th><th class="m">Last Modified</th><th class="s">Size</th><th class="t">Type</th></tr></thead>
+<tbody>
+<tr><td class="n"><a href="../">Parent Directory</a>/</td><td class="m"> </td><td class="s">- </td><td class="t">Directory</td></tr>
+<tr><td class="n"><a href="archives/">archives</a>/</td><td class="m">2024-Jan-16 09:01:57</td><td class="s">- </td><td class="t">Directory</td></tr>
+<tr><td class="n"><a href="com/">com</a>/</td><td class="m">2016-Sep-22 22:23:10</td><td class="s">- </td><td class="t">Directory</td></tr>
+<tr><td class="n"><a href="dev/">dev</a>/</td><td class="m">2023-Nov-22 18:56:34</td><td class="s">- </td><td class="t">Directory</td></tr>
+<tr><td class="n"><a href="listes-galette/">listes-galette</a>/</td><td class="m">2017-Feb-02 02:06:43</td><td class="s">- </td><td class="t">Directory</td></tr>
+<tr><td class="n"><a href="plugins/">plugins</a>/</td><td class="m">2024-Jan-16 17:23:37</td><td class="s">- </td><td class="t">Directory</td></tr>
+<tr><td class="n"><a href="README">README</a></td><td class="m">2021-Sep-22 07:29:48</td><td class="s">0.1K</td><td class="t">text/plain</td></tr>
+<tr><td class="n"><a href="galette-1.0.0.tar.bz2">galette-1.0.0.tar.bz2</a></td><td class="m">2023-Dec-07 07:57:12</td><td class="s">8.7M</td><td class="t">application/octet-stream</td></tr>
+<tr><td class="n"><a href="galette-1.0.1.tar.bz2">galette-1.0.1.tar.bz2</a></td><td class="m">2024-Jan-16 09:00:19</td><td class="s">8.7M</td><td class="t">application/octet-stream</td></tr>
+<tr><td class="n"><a href="galette-1.0.2.tar.bz2">galette-1.0.2.tar.bz2</a></td><td class="m">2024-Feb-03 09:32:46</td><td class="s">8.7M</td><td class="t">application/octet-stream</td></tr>
+<tr><td class="n"><a href="galette-1.0.2.tar.bz2.asc">galette-1.0.2.tar.bz2.asc</a></td><td class="m">2024-Feb-03 09:32:46</td><td class="s">0.1K</td><td class="t">text/plain</td></tr>
+<tr><td class="n"><a href="galette-dev.tar.bz2">galette-dev.tar.bz2</a></td><td class="m">2024-Feb-16 00:34:58</td><td class="s">8.7M</td><td class="t">application/octet-stream</td></tr>
+<tr><td class="n"><a href="galette-dev.tar.bz2.asc">galette-dev.tar.bz2.asc</a></td><td class="m">2023-Oct-19 17:32:27</td><td class="s">0.1K</td><td class="t">text/plain</td></tr>
+</tbody>
+</table>
+</div>
+<div class="foot">lighttpd/1.4.35</div>
+</body>
+</html>' //real content as of 1.0.2 release
+ ],
+ [
+ '1.0.0',
+ '1.1.0',
+ true,
+ '<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<title>Index of /galette/</title>
+<style type="text/css">
+a, a:active {text-decoration: none; color: blue;}
+a:visited {color: #48468F;}
+a:hover, a:focus {text-decoration: underline; color: red;}
+body {background-color: #F5F5F5;}
+h2 {margin-bottom: 12px;}
+table {margin-left: 12px;}
+th, td { font: 90% monospace; text-align: left;}
+th { font-weight: bold; padding-right: 14px; padding-bottom: 3px;}
+td {padding-right: 14px;}
+td.s, th.s {text-align: right;}
+div.list { background-color: white; border-top: 1px solid #646464; border-bottom: 1px solid #646464; padding-top: 10px; padding-bottom: 14px;}
+div.foot { font: 90% monospace; color: #787878; padding-top: 4px;}
+</style>
+</head>
+<body>
+<h2>Index of /galette/</h2>
+<div class="list">
+<table summary="Directory Listing" cellpadding="0" cellspacing="0">
+<thead><tr><th class="n">Name</th><th class="m">Last Modified</th><th class="s">Size</th><th class="t">Type</th></tr></thead>
+<tbody>
+<tr><td class="n"><a href="../">Parent Directory</a>/</td><td class="m"> </td><td class="s">- </td><td class="t">Directory</td></tr>
+<tr><td class="n"><a href="archives/">archives</a>/</td><td class="m">2024-Jan-16 09:01:57</td><td class="s">- </td><td class="t">Directory</td></tr>
+<tr><td class="n"><a href="com/">com</a>/</td><td class="m">2016-Sep-22 22:23:10</td><td class="s">- </td><td class="t">Directory</td></tr>
+<tr><td class="n"><a href="dev/">dev</a>/</td><td class="m">2023-Nov-22 18:56:34</td><td class="s">- </td><td class="t">Directory</td></tr>
+<tr><td class="n"><a href="listes-galette/">listes-galette</a>/</td><td class="m">2017-Feb-02 02:06:43</td><td class="s">- </td><td class="t">Directory</td></tr>
+<tr><td class="n"><a href="plugins/">plugins</a>/</td><td class="m">2024-Jan-16 17:23:37</td><td class="s">- </td><td class="t">Directory</td></tr>
+<tr><td class="n"><a href="README">README</a></td><td class="m">2021-Sep-22 07:29:48</td><td class="s">0.1K</td><td class="t">text/plain</td></tr>
+<tr><td class="n"><a href="galette-1.0.0.tar.bz2">galette-1.0.0.tar.bz2</a></td><td class="m">2023-Dec-07 07:57:12</td><td class="s">8.7M</td><td class="t">application/octet-stream</td></tr>
+<tr><td class="n"><a href="galette-1.0.1.tar.bz2">galette-1.0.1.tar.bz2</a></td><td class="m">2024-Jan-16 09:00:19</td><td class="s">8.7M</td><td class="t">application/octet-stream</td></tr>
+<tr><td class="n"><a href="galette-1.0.2.tar.bz2">galette-1.0.2.tar.bz2</a></td><td class="m">2024-Feb-03 09:32:46</td><td class="s">8.7M</td><td class="t">application/octet-stream</td></tr>
+<tr><td class="n"><a href="galette-1.0.2.tar.bz2.asc">galette-1.0.2.tar.bz2.asc</a></td><td class="m">2024-Feb-03 09:32:46</td><td class="s">0.1K</td><td class="t">text/plain</td></tr>
+<tr><td class="n"><a href="galette-1.1.0.tar.bz2">galette-1.1.0.tar.bz2</a></td><td class="m">2024-Feb-16 09:09:13</td><td class="s">10M</td><td class="t">application/octet-stream</td></tr>
+<tr><td class="n"><a href="galette-1.1.0.tar.bz2.asc">galette-1.1.0.tar.bz2.asc</a></td><td class="m">2024-Feb-16 09:09:13</td><td class="s">0.1K</td><td class="t">text/plain</td></tr>
+<tr><td class="n"><a href="galette-dev.tar.bz2">galette-dev.tar.bz2</a></td><td class="m">2024-Feb-16 00:34:58</td><td class="s">8.7M</td><td class="t">application/octet-stream</td></tr>
+<tr><td class="n"><a href="galette-dev.tar.bz2.asc">galette-dev.tar.bz2.asc</a></td><td class="m">2023-Oct-19 17:32:27</td><td class="s">0.1K</td><td class="t">text/plain</td></tr>
+</tbody>
+</table>
+</div>
+<div class="foot">lighttpd/1.4.35</div>
+</body>
+</html>' //fakse 1.1.0 release
+ ],
+ [
+ '1.1.0',
+ '1.1.0',
+ false,
+ '<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<body>
+<div class="list">
+<table summary="Directory Listing" cellpadding="0" cellspacing="0">
+<tbody>
+<tr><td class="n"><a href="galette-1.1.0.tar.bz2">galette-1.1.0.tar.bz2</a></td><td class="m">2024-Feb-16 09:09:13</td><td class="s">10M</td><td class="t">application/octet-stream</td></tr>
+</tbody>
+</table>
+</div>
+</body>
+</html>' //fake 1.1.0 release
+ ],
+ [
+ '1.2.0',
+ '1.1.0',
+ false,
+ '<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<body>
+<div class="list">
+<table summary="Directory Listing" cellpadding="0" cellspacing="0">
+<tbody>
+<tr><td class="n"><a href="galette-1.1.0.tar.bz2">galette-1.1.0.tar.bz2</a></td><td class="m">2024-Feb-16 09:09:13</td><td class="s">10M</td><td class="t">application/octet-stream</td></tr>
+</tbody>
+</table>
+</div>
+</body>
+</html>' //fake 1.1.0 release
+ ],
+ ];
+ }
+
+ /**
+ * Test findLatestRelease
+ *
+ * @param string $current Current release
+ * @param string $latest Latest release
+ * @param bool $expected Expected result
+ * @param string $page Page content
+ *
+ * @dataProvider releasesPageProvider
+ * @return void
+ */
+ public function testFindLatestRelease(string $current, string $latest, bool $expected, string $page): void
+ {
+ $release = $this->getMockBuilder(\Galette\Util\Release::class)
+ ->onlyMethods(array('setupClient', 'getCurrentRelease'))
+ ->getMock();
+
+ // Create a mock and queue two responses.
+ $mock = new \GuzzleHttp\Handler\MockHandler([
+ new \GuzzleHttp\Psr7\Response(
+ 200,
+ ['X-Foo' => 'Bar'],
+ $page
+ )
+ ]);
+
+ $handlerStack = \GuzzleHttp\HandlerStack::create($mock);
+ $client = new \GuzzleHttp\Client(['handler' => $handlerStack]);
+
+ $release->method('getCurrentRelease')->willReturn($current);
+ $release->method('setupClient')->willReturnCallback(function () use ($client) {
+ return $client;
+ });
+
+ $this->assertSame($expected, $release->checkNewRelease());
+ $this->assertSame($latest, $release->getLatestRelease());
+ }
+}