Skip to content

Commit ca6617b

Browse files
committed
Merge branch 'release/4.1.18' into v4
2 parents 12fad0c + 78cb7be commit ca6617b

35 files changed

+1109
-925
lines changed

CHANGELOG.md

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

3+
## 4.1.18 - 2025.10.06
4+
### Added
5+
* Added a `twigExtensionClasses` config setting to allow additional TwigExtension classes to be loaded in the Twig `SandboxView` that SEOmatic uses to render ([#1632](https://github.com/nystudio107/craft-seomatic/issues/1632))
6+
* Only allow users to pick SEO/Facebook/Twitter images from asset volumes that they had permission to access ([#1650](https://github.com/nystudio107/craft-seomatic/issues/1650))
7+
8+
### Changed
9+
* No longer block various AI bots via `robots.txt` by default ([#1635](https://github.com/nystudio107/craft-seomatic/issues/1635))
10+
* Handle setting the focal point for social images that are transformed ([#1626](https://github.com/nystudio107/craft-seomatic/issues/1626))
11+
12+
### Fixed
13+
* Fixed an issue with page footer text being untranslatable on 3 pages due to filter ordering ([#1651](https://github.com/nystudio107/craft-seomatic/issues/1651))
14+
* Don't overwrite the `dataLayer` if it already exists in the Google Tag Manager default script ([#1642](https://github.com/nystudio107/craft-seomatic/issues/1642))
15+
316
## 4.1.17 - 2025.08.17
417
### Changed
518
* Use `StringHelper::convertToUtf8()` instead of our homebrew solution

buildchain/package-lock.json

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

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "nystudio107/craft-seomatic",
33
"description": "SEOmatic facilitates modern SEO best practices & implementation for Craft CMS 4. It is a turnkey SEO system that is comprehensive, powerful, and flexible.",
44
"type": "craft-plugin",
5-
"version": "4.1.17",
5+
"version": "4.1.18",
66
"keywords": [
77
"craft",
88
"cms",
@@ -34,7 +34,7 @@
3434
"craftcms/cms": "^4.0.0",
3535
"nystudio107/craft-plugin-vite": "^4.0.7",
3636
"nystudio107/craft-code-editor": "^1.0.0",
37-
"nystudio107/craft-twig-sandbox": "^4.0.3",
37+
"nystudio107/craft-twig-sandbox": "^4.0.5",
3838
"php-science/textrank": "^1.0.3",
3939
"davechild/textstatistics": "^1.0.3",
4040
"sunra/php-simple-html-dom-parser": "^1.5.2"

docs/package-lock.json

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

src/Seomatic.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,12 @@ protected function installEventListeners(): void
428428
$seomaticTwigExtension = new SeomaticTwigExtension();
429429
self::$view->registerTwigExtension($seomaticTwigExtension);
430430
self::$sandboxView->registerTwigExtension($seomaticTwigExtension);
431+
// Register the additional TwigExtension classes
432+
foreach (Seomatic::$settings->twigExtensionClasses as $className) {
433+
if (class_exists($className)) {
434+
self::$sandboxView->registerTwigExtension(new $className());
435+
}
436+
}
431437
$request = Craft::$app->getRequest();
432438
// Add in our event listeners that are needed for every request
433439
$this->installGlobalEventListeners();

src/config.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,7 @@
174174
// string[] URL params that are allowed to be considered part of the unique URL used for the metadata cache
175175
'allowedUrlParams' => [
176176
],
177+
// class-string[] Array of TwigExtension classes to instantiate and add to the SandboxView
178+
'twigExtensionClasses' => [
179+
],
177180
];

src/controllers/SettingsController.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use nystudio107\seomatic\assetbundles\seomatic\SeomaticAsset;
2121
use nystudio107\seomatic\autocompletes\TrackingVarsAutocomplete;
2222
use nystudio107\seomatic\helpers\ArrayHelper;
23+
use nystudio107\seomatic\helpers\AssetHelper;
2324
use nystudio107\seomatic\helpers\DynamicMeta as DynamicMetaHelper;
2425
use nystudio107\seomatic\helpers\Field as FieldHelper;
2526
use nystudio107\seomatic\helpers\ImageTransform as ImageTransformHelper;
@@ -320,6 +321,7 @@ public function actionGlobal(string $subSection = 'general', string $siteHandle
320321
// Image selectors
321322
$bundleSettings = $metaBundle->metaBundleSettings;
322323
$variables['elementType'] = Asset::class;
324+
$variables['assetVolumeSources'] = AssetHelper::getAssetInputSources();
323325
$variables['seoImageElements'] = ImageTransformHelper::assetElementsFromIds(
324326
$bundleSettings->seoImageIds,
325327
$siteId
@@ -619,6 +621,7 @@ public function actionEditContent(
619621
$variables['currentSubSection'] = $subSection;
620622
$bundleSettings = $metaBundle->metaBundleSettings;
621623
$variables['elementType'] = Asset::class;
624+
$variables['assetVolumeSources'] = AssetHelper::getAssetInputSources();
622625
$variables['seoImageElements'] = ImageTransformHelper::assetElementsFromIds(
623626
$bundleSettings->seoImageIds,
624627
$siteId
@@ -799,6 +802,7 @@ public function actionSite(string $subSection = 'identity', string $siteHandle =
799802
);
800803
}
801804
$variables['elementType'] = Asset::class;
805+
$variables['assetVolumeSources'] = AssetHelper::getAssetInputSources();
802806

803807
// Render the template
804808
return $this->renderTemplate('seomatic/settings/site/' . $subSection, $variables);

src/fields/SeoSettings.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use craft\helpers\StringHelper;
2020
use nystudio107\seomatic\assetbundles\seomatic\SeomaticAsset;
2121
use nystudio107\seomatic\helpers\ArrayHelper;
22+
use nystudio107\seomatic\helpers\AssetHelper;
2223
use nystudio107\seomatic\helpers\Config as ConfigHelper;
2324
use nystudio107\seomatic\helpers\Field as FieldHelper;
2425
use nystudio107\seomatic\helpers\Migration as MigrationHelper;
@@ -348,7 +349,7 @@ public function getInputHtml(mixed $value, ?ElementInterface $element = null): s
348349

349350
/** @var MetaBundle $value */
350351
$variables['elementType'] = Asset::class;
351-
352+
$variables['assetVolumeSources'] = AssetHelper::getAssetInputSources();
352353
$variables['parentBundles'] = [];
353354
// Preview the containers so the preview is correct in the field
354355
if ($element !== null && $element->uri !== null) {

src/helpers/AssetHelper.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
/**
3+
* SEOmatic plugin for Craft CMS
4+
*
5+
* A turnkey SEO implementation for Craft CMS that is comprehensive, powerful,
6+
* and flexible
7+
*
8+
* @link https://nystudio107.com
9+
* @copyright Copyright (c) nystudio107
10+
*/
11+
12+
namespace nystudio107\seomatic\helpers;
13+
14+
use Craft;
15+
use craft\elements\Asset;
16+
use craft\fs\Temp;
17+
use craft\helpers\ArrayHelper;
18+
use craft\services\ElementSources;
19+
20+
/**
21+
* @author nystudio107
22+
* @package Seomatic
23+
* @since 4.1.18
24+
*/
25+
class AssetHelper
26+
{
27+
/**
28+
* Return asset volume sources that can be accessed by the current user
29+
*
30+
* @return array
31+
*/
32+
public static function getAssetInputSources(): array
33+
{
34+
$sources = [];
35+
foreach (Craft::$app->getElementSources()->getSources(Asset::class) as $source) {
36+
if ($source['type'] !== ElementSources::TYPE_HEADING) {
37+
$sources[] = $source['key'];
38+
}
39+
}
40+
41+
$userService = Craft::$app->getUser();
42+
$volumesService = Craft::$app->getVolumes();
43+
return ArrayHelper::where($sources, function(string $source) use ($volumesService, $userService) {
44+
// If it’s not a volume folder, let it through
45+
if (!str_starts_with($source, 'volume:')) {
46+
return true;
47+
}
48+
// Only show it if they have permission to view it, or if it's the temp volume
49+
$volumeUid = explode(':', $source)[1];
50+
if ($userService->checkPermission("viewAssets:$volumeUid")) {
51+
return true;
52+
}
53+
$volume = $volumesService->getVolumeByUid($volumeUid);
54+
return $volume?->getFs() instanceof Temp;
55+
}, true, true, false);
56+
}
57+
}

src/helpers/ImageTransform.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ public static function socialTransform(
148148
}
149149
}
150150
try {
151+
if ($asset->getHasFocalPoint()) {
152+
$transform->position = $asset->getFocalPoint(true);
153+
}
151154
$url = $asset->getUrl($transform, $generateNow);
152155
} catch (InvalidConfigException $e) {
153156
$url = null;

0 commit comments

Comments
 (0)