Skip to content

Commit ea13abe

Browse files
committed
Merge branch 'release/5.0.12' into v5
2 parents f34d15d + 08799f0 commit ea13abe

File tree

63 files changed

+1880
-1917
lines changed

Some content is hidden

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

63 files changed

+1880
-1917
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Retour Changelog
22

3+
## 5.0.12 - 2025.08.17
4+
### Changed
5+
* Use `StringHelper::convertToUtf8()` instead of our homebrew solution
6+
* Throw an exception if an attempt is made to edit a redirect that doesn't exist ([#345](https://github.com/nystudio107/craft-retour/issues/345))
7+
8+
### Fixed
9+
* Fixed a regression that caused the redirect loop detection to no longer function ([#348](https://github.com/nystudio107/craft-retour/issues/348))
10+
311
## 5.0.11 - 2025.06.13
412
### Changed
513
* Allow `RedirectEvent`s to change the redirect that is saved ([#342](https://github.com/nystudio107/craft-retour/issues/342))

buildchain/package-lock.json

Lines changed: 523 additions & 600 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "nystudio107/craft-retour",
33
"description": "Retour allows you to intelligently redirect legacy URLs, so that you don't lose SEO value when rebuilding & restructuring a website",
44
"type": "craft-plugin",
5-
"version": "5.0.11",
5+
"version": "5.0.12",
66
"keywords": [
77
"craftcms",
88
"craft-plugin",

docs/package-lock.json

Lines changed: 300 additions & 283 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/controllers/RedirectsController.php

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use nystudio107\retour\helpers\Permission as PermissionHelper;
2424
use nystudio107\retour\models\StaticRedirects as StaticRedirectsModel;
2525
use nystudio107\retour\Retour;
26+
use Throwable;
2627
use yii\base\Exception;
2728
use yii\base\InvalidConfigException;
2829
use yii\web\BadRequestHttpException;
@@ -138,15 +139,7 @@ public function actionEditRedirect(
138139
if ($redirect === null) {
139140
$redirectConfig = Retour::$plugin->redirects->getRedirectById($redirectId);
140141
if ($redirectConfig === null) {
141-
$redirectConfig = [];
142-
Craft::error(
143-
Craft::t(
144-
'retour',
145-
"Couldn't load redirect id {id}",
146-
['id' => $redirectId]
147-
),
148-
__METHOD__
149-
);
142+
throw new NotFoundHttpException('Redirect not found');
150143
}
151144
$redirect = new StaticRedirectsModel($redirectConfig);
152145
}
@@ -284,7 +277,7 @@ public function actionSaveRedirect(): ?Response
284277
}
285278
// Save the redirect
286279
$redirectConfig = $redirect->getAttributes();
287-
Retour::$plugin->redirects->saveRedirect($redirectConfig);
280+
Retour::$plugin->redirects->saveRedirect($redirectConfig, false);
288281
// Handle the case where the redirect wasn't saved because it'd create a redirect loop
289282
$testRedirectConfig = Retour::$plugin->redirects->getRedirectByRedirectSrcUrl(
290283
$redirectConfig['redirectSrcUrl'],
@@ -314,8 +307,8 @@ public function actionSaveRedirect(): ?Response
314307
* @param string|null $siteHandle
315308
*
316309
* @return Response
317-
* @throws \yii\web\ForbiddenHttpException
318-
* @throws \yii\web\NotFoundHttpException
310+
* @throws ForbiddenHttpException
311+
* @throws NotFoundHttpException
319312
*/
320313
public function actionShortlinks(string $siteHandle = null): Response
321314
{
@@ -368,7 +361,7 @@ public function actionShortlinks(string $siteHandle = null): Response
368361
* @throws BadRequestHttpException
369362
* @throws ForbiddenHttpException
370363
* @throws MissingComponentException
371-
* @throws \Throwable
364+
* @throws Throwable
372365
* @throws ElementNotFoundException
373366
* @throws Exception
374367
*/

src/helpers/Text.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111

1212
namespace nystudio107\retour\helpers;
1313

14+
use craft\helpers\StringHelper;
1415
use Stringy\Stringy;
15-
use function function_exists;
1616

1717
/**
1818
* @author nystudio107
@@ -88,12 +88,7 @@ public static function cleanupText(string $text): string
8888
return '';
8989
}
9090
// Convert to UTF-8
91-
if (function_exists('iconv')) {
92-
$text = iconv(mb_detect_encoding($text, mb_detect_order(), true), 'UTF-8//IGNORE', $text);
93-
} else {
94-
ini_set('mbstring.substitute_character', 'none');
95-
$text = mb_convert_encoding($text, 'UTF-8', 'UTF-8');
96-
}
91+
$text = StringHelper::convertToUtf8($text);
9792
// Strip HTML tags
9893
$text = strip_tags($text);
9994
// Remove excess whitespace

src/services/Redirects.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1115,9 +1115,10 @@ public function deleteShortlinkById(int $redirectId): bool
11151115

11161116
/**
11171117
* @param array $redirectConfig
1118+
* @param bool $checkForRedirectLoop
11181119
* @return bool
11191120
*/
1120-
public function saveRedirect(array $redirectConfig): bool
1121+
public function saveRedirect(array $redirectConfig, bool $checkForRedirectLoop = true): bool
11211122
{
11221123
// Handle URL encoded URLs by decoding them before saving them
11231124
if (isset($redirectConfig['redirectMatchType']) && $redirectConfig['redirectMatchType'] === 'exactmatch') {
@@ -1230,6 +1231,32 @@ public function saveRedirect(array $redirectConfig): bool
12301231
return false;
12311232
}
12321233
}
1234+
if ($checkForRedirectLoop) {
1235+
// To prevent redirect loops, see if any static redirects have our redirectDestUrl as their redirectSrcUrl
1236+
$testRedirectConfig = $this->getRedirectByRedirectSrcUrl(
1237+
$redirectConfig['redirectDestUrl'],
1238+
$redirectConfig['siteId']
1239+
);
1240+
if ($testRedirectConfig !== null) {
1241+
Craft::debug(
1242+
Craft::t(
1243+
'retour',
1244+
'Deleting redirect to prevent a loop: {redirect}',
1245+
['redirect' => print_r($testRedirectConfig, true)]
1246+
),
1247+
__METHOD__
1248+
);
1249+
// Delete the redirect that has a redirectSrcUrl the same as this record's redirectDestUrl
1250+
try {
1251+
$db->createCommand()->delete(
1252+
'{{%retour_static_redirects}}',
1253+
['id' => $testRedirectConfig['id']]
1254+
)->execute();
1255+
} catch (Exception $e) {
1256+
Craft::error($e->getMessage(), __METHOD__);
1257+
}
1258+
}
1259+
}
12331260
// Trigger a 'afterSaveRedirect' event
12341261
$this->trigger(self::EVENT_AFTER_SAVE_REDIRECT, $event);
12351262

0 commit comments

Comments
 (0)