Skip to content

Commit

Permalink
Merge branch 'release/4.4.10' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonkelly committed May 9, 2023
2 parents 0c111e4 + 32722f4 commit 0fab7ae
Show file tree
Hide file tree
Showing 33 changed files with 136 additions and 70 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Release Notes for Craft CMS 4

## 4.4.10 - 2023-05-09

- PHP warnings and notices no longer halt execution when Dev Mode is disabled. ([#13164](https://github.com/craftcms/cms/issues/13164))
- Fixed a “Double-instantiating a menu button on an element” console warning that occurred on pages with Matrix fields. ([#6338](https://github.com/craftcms/cms/issues/6338))
- Fixed a bug where Quick Post widget settings weren’t filtering custom field options for the selected entry type.
- Fixed a bug where Matrix blocks could get detached from entries when sections were enabled for a new site. ([#13155](https://github.com/craftcms/cms/issues/13155))
- Fixed an error that could occur when entrifying a global set without a field layout. ([#13156](https://github.com/craftcms/cms/issues/13156))
- Fixed a bug where Single entries’ edit pages could have “Save and add another” actions. ([#13157](https://github.com/craftcms/cms/issues/13157))
- Fixed styling issues with Date fields. ([#13167](https://github.com/craftcms/cms/issues/13167))
- Fixed the vertical alignment of element labels. ([#13168](https://github.com/craftcms/cms/issues/13168))
- Fixed a bug where the System Report utility could display MariaDB’s MySQL-equivalent version, if it was listed first in the server version string.
- Added `craft\helpers\ArrayHelper::containsRecursive()`.
- `craft\helpers\App::normalizeVersion()` now returns the highest version found before distribution info.

## 4.4.9 - 2023-05-02

- Volumes no longer validate if their field layout contains a field called `extension`, `filename`, `height`, `kind`, `size`, or `width`.
Expand Down
6 changes: 5 additions & 1 deletion bootstrap/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@
}
}

error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
$errorLevel = E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED;
error_reporting($errorLevel);

// Load the general config
// -----------------------------------------------------------------------------
Expand All @@ -179,6 +180,9 @@
ini_set('display_errors', '0');
defined('YII_DEBUG') || define('YII_DEBUG', false);
defined('YII_ENV') || define('YII_ENV', 'prod');

// don't let PHP warnings & notices halt execution
error_reporting($errorLevel & ~E_WARNING & ~E_NOTICE);
}

// Load the Composer dependencies and the app
Expand Down
2 changes: 1 addition & 1 deletion src/base/ElementInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ public static function findSource(string $sourceKey, ?string $context = null): ?
public static function fieldLayouts(string $source): array;

/**
* Returns the available [element actions](https://craftcms.com/docs/4.x/extend/element-action-types.html) for a
* Returns the available [element actions](https://craftcms.com/docs/4.x/extend/element-actions.html) for a
* given source.
*
* The actions can be represented by their fully qualified class name, a config array with the class name
Expand Down
2 changes: 1 addition & 1 deletion src/config/GeneralConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -2469,7 +2469,7 @@ class GeneralConfig extends BaseConfig
public bool $sanitizeCpImageUploads = true;

/**
* @var string|null The [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) value that should be set on Craft cookies, if any.
* @var string|null The [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) value that should be set on Craft cookies, if any.
* @phpstan-var 'None'|'Lax'|'Strict'|null
*
* This can be set to `'None'`, `'Lax'`, `'Strict'`, or `null`.
Expand Down
2 changes: 1 addition & 1 deletion src/config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
return [
'id' => 'CraftCMS',
'name' => 'Craft CMS',
'version' => '4.4.9',
'version' => '4.4.10',
'schemaVersion' => '4.4.0.4',
'minVersionRequired' => '3.7.11',
'basePath' => dirname(__DIR__), // Defines the @app alias
Expand Down
2 changes: 1 addition & 1 deletion src/console/controllers/SectionsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ public function actionCreate(): int
if ($saveEntryType) {
$this->do('Saving the entry type', function() use ($entryType, $sourceFieldLayout) {
if ($sourceFieldLayout) {
$fieldLayout = FieldLayout::createFromConfig($sourceFieldLayout->getConfig());
$fieldLayout = FieldLayout::createFromConfig($sourceFieldLayout->getConfig() ?? []);
foreach ($fieldLayout->getTabs() as $tab) {
$tab->uid = StringHelper::UUID();
foreach ($tab->getElements() as $element) {
Expand Down
2 changes: 1 addition & 1 deletion src/db/mysql/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public function createColumnSchemaBuilder($type, $length = null): ColumnSchemaBu
public function getDefaultBackupCommand(?array $ignoreTables = null): string
{
$useSingleTransaction = true;
$serverVersion = App::normalizeVersion(Craft::$app->getDb()->getSchema()->getServerVersion());
$serverVersion = App::normalizeVersion($this->getServerVersion());

$isMySQL5 = version_compare($serverVersion, '8', '<');
$isMySQL8 = version_compare($serverVersion, '8', '>=');
Expand Down
5 changes: 4 additions & 1 deletion src/elements/Entry.php
Original file line number Diff line number Diff line change
Expand Up @@ -1317,7 +1317,10 @@ public function canSave(User $user): bool
$section = $this->getSection();

if (!$this->id) {
return $user->can("createEntries:$section->uid");
return (
$section->type !== Section::TYPE_SINGLE &&
$user->can("createEntries:$section->uid")
);
}

if ($this->getIsDraft()) {
Expand Down
19 changes: 17 additions & 2 deletions src/helpers/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -410,14 +410,29 @@ public static function normalizeValue(mixed $value): mixed
}

/**
* Removes distribution info from a version
* Removes distribution info from a version string, and returns the highest version number found in the remainder.
*
* @param string $version
* @return string
*/
public static function normalizeVersion(string $version): string
{
return preg_replace('/^([^\s~+-]+).*$/', '$1', $version);
// Strip out the distribution info
$versionPattern = '\d[\d.]*(-(dev|alpha|beta|rc)(\.?\d[\d.]*)?)?';
if (!preg_match("/^((v|version\s*)?$versionPattern-?)+/i", $version, $match)) {
return '';
}
$version = $match[0];

// Return the highest version
preg_match_all("/$versionPattern/i", $version, $matches, PREG_SET_ORDER);
$versions = array_map(fn(array $match) => $match[0], $matches);
usort($versions, fn($a, $b) => match (true) {
version_compare($a, $b, '<') => 1,
version_compare($a, $b, '>') => -1,
default => 0,
});
return reset($versions) ?: '';
}

/**
Expand Down
28 changes: 28 additions & 0 deletions src/helpers/ArrayHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,34 @@ public static function contains(iterable $array, callable|string $key, mixed $va
return false;
}

/**
* Returns whether the given array, or any nested arrays, contain any values where a given key (the name of a
* sub-array key or sub-object property) is set to a given value.
*
* @param iterable $array the array that the value will be searched for in
* @param callable|string $key the column name or anonymous function which must be set to $value
* @param mixed $value the value that $key should be compared with
* @param bool $strict whether a strict type comparison should be used when checking array element values against $value
* @return bool whether the value exists in the array, recursively
* @since 4.4.10
*/
public static function containsRecursive(iterable $array, callable|string $key, mixed $value = true, bool $strict = false): bool
{
foreach ($array as $element) {
$elementValue = static::getValue($element, $key);
/** @noinspection TypeUnsafeComparisonInspection */
if (($strict && $elementValue === $value) || (!$strict && $elementValue == $value)) {
return true;
}

if (is_array($element) && static::containsRecursive($element, $key, $value, $strict)) {
return true;
}
}

return false;
}

/**
* Returns whether the given array contains *only* values where a given key (the name of a
* -ub-array key or sub-object property) is sett o given value.
Expand Down
7 changes: 6 additions & 1 deletion src/services/Matrix.php
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,12 @@ public function saveField(MatrixField $field, ElementInterface $owner): void
/** @var MatrixBlock[] $blocks */
foreach ($blocks as $block) {
$sortOrder++;
if ($saveAll || !$block->id || $block->dirty) {
if (
// skip blocks that are primarily owned by a different element
($saveAll && (!$block->primaryOwnerId || $block->primaryOwnerId === $owner->id)) ||
!$block->id ||
$block->dirty
) {
$block->primaryOwnerId = $block->ownerId = $owner->id;
$block->sortOrder = $sortOrder;
$elementsService->saveElement($block, false);
Expand Down
6 changes: 3 additions & 3 deletions src/services/Utilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@
class Utilities extends Component
{
/**
* @event RegisterComponentTypesEvent The event that is triggered when registering utility types.
* @event RegisterComponentTypesEvent The event that is triggered when registering utilities.
*
* Utility types must implement [[UtilityInterface]]. [[\craft\base\Utility]] provides a base implementation.
* Utilities must implement [[UtilityInterface]]. [[\craft\base\Utility]] provides a base implementation.
*
* See [Utility Types](https://craftcms.com/docs/4.x/extend/utility-types.html) for documentation on creating utility types.
* Read more about creating utilities in the [documentation](https://craftcms.com/docs/4.x/extend/utilities.html).
* ---
* ```php
* use craft\events\RegisterComponentTypesEvent;
Expand Down
42 changes: 18 additions & 24 deletions src/templates/_components/widgets/QuickPost/settings.twig
Original file line number Diff line number Diff line change
Expand Up @@ -64,31 +64,25 @@
}) }}
{% endif %}

{% set fieldCheckboxes = [] %}
{% set fieldsInput %}
{% set entryTypes = section.getEntryTypes() %}
{% for entryType in entryTypes %}
{% set showEntryType = (((not showSection or not widget.entryType) and loop.first) or widget.entryType == entryType.id or entryTypes|length == 1) %}
<div id="section{{ section.id }}-type{{ entryType.id }}"{% if not showEntryType %} class="hidden"{% endif %}>
{% for layoutElement in fieldsByEntryTypeId[entryType.id] ?? [] %}
{% set field = layoutElement.getField() %}
{% set fieldCheckboxes = fieldCheckboxes|merge([{
label: raw(field.name|e ~ (layoutElement.required ? '<span class="required"></span>')),
name: 'sections['~section.id~'][fields][]',
value: field.id,
checked: (layoutElement.required or field.id in widget.fields),
disabled: layoutElement.required
}]) %}
{% endfor %}
</div>
{% endfor %}
{% endset %}
{% set entryTypes = section.getEntryTypes() %}
{% for entryType in entryTypes %}
{% set showEntryType = (((not showSection or not widget.entryType) and loop.first) or widget.entryType == entryType.id or entryTypes|length == 1) %}
{% set fieldOptions = (fieldsByEntryTypeId[entryType.id] ?? [])|map(layoutElement => {
label: raw(layoutElement.getField().name|e ~ (layoutElement.required ? '<span class="required"></span>')),
name: 'sections['~section.id~'][fields][]',
value: layoutElement.getField().id,
checked: (layoutElement.required or layoutElement.getField().id in widget.fields),
disabled: layoutElement.required
}) %}

{{ forms.checkboxGroupField({
label: "Fields"|t('app'),
instructions: "Which fields should be visible in the widget?"|t('app'),
options: fieldCheckboxes,
}) }}
<div id="section{{ section.id }}-type{{ entryType.id }}"{% if not showEntryType %} class="hidden"{% endif %}>
{{ forms.checkboxGroupField({
label: "Fields"|t('app'),
instructions: "Which fields should be visible in the widget?"|t('app'),
options: fieldOptions,
}) }}
</div>
{% endfor %}
</div>
{% endfor %}

Expand Down
2 changes: 1 addition & 1 deletion src/web/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,6 @@ public function end($status = 0, $response = null)
throw new ExitException();
}

parent::end($status, $response); // TODO: Change the autogenerated stub
parent::end($status, $response);
}
}
3 changes: 1 addition & 2 deletions src/web/assets/admintable/dist/css/app.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion src/web/assets/admintable/dist/css/app.css.map

This file was deleted.

2 changes: 1 addition & 1 deletion src/web/assets/admintable/dist/js/app.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/web/assets/admintable/dist/js/app.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/web/assets/admintable/dist/manifest.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"app.css":"/css/app.css","app.js":"/js/app.js","app.css.map":"/css/app.css.map","app.js.map":"/js/app.js.map"}
{"app.css":"/css/app.css","app.js":"/js/app.js","app.js.map":"/js/app.js.map"}
2 changes: 1 addition & 1 deletion src/web/assets/cp/dist/css/cp.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/web/assets/cp/dist/css/cp.css.map

Large diffs are not rendered by default.

Loading

0 comments on commit 0fab7ae

Please sign in to comment.