diff --git a/bundles/AdminBundle/Resources/public/js/pimcore/object/fieldcollection.js b/bundles/AdminBundle/Resources/public/js/pimcore/object/fieldcollection.js index 555e55d6280..dc8d1214b2c 100644 --- a/bundles/AdminBundle/Resources/public/js/pimcore/object/fieldcollection.js +++ b/bundles/AdminBundle/Resources/public/js/pimcore/object/fieldcollection.js @@ -189,7 +189,7 @@ pimcore.object.fieldcollection = Class.create({ addFieldComplete: function (button, value, object) { - var isValidName = /^[a-zA-Z]+$/; + var isValidName = /^[a-zA-Z][a-zA-Z0-9]*$/; if (button == "ok" && value.length > 2 && isValidName.test(value) && !in_arrayi(value, this.forbiddenNames)) { Ext.Ajax.request({ diff --git a/bundles/CoreBundle/DependencyInjection/Configuration.php b/bundles/CoreBundle/DependencyInjection/Configuration.php index 4ca2f9a4f42..45a3b2388c7 100644 --- a/bundles/CoreBundle/DependencyInjection/Configuration.php +++ b/bundles/CoreBundle/DependencyInjection/Configuration.php @@ -1807,7 +1807,7 @@ private function addWorkflowNode(ArrayNodeDefinition $rootNode) ->scalarNode('guard') ->cannotBeEmpty() ->info('An expression to block the transition') - ->example('is_fully_authenticated() and has_role(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'') + ->example('is_fully_authenticated() and is_granted(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'') ->end() ->arrayNode('from') ->beforeNormalization() @@ -1975,7 +1975,7 @@ private function addWorkflowNode(ArrayNodeDefinition $rootNode) ->scalarNode('guard') ->cannotBeEmpty() ->info('An expression to block the action') - ->example('is_fully_authenticated() and has_role(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'') + ->example('is_fully_authenticated() and is_granted(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'') ->end() ->arrayNode('to') ->beforeNormalization() diff --git a/composer.json b/composer.json index ac0ed898cc4..3fdadfda736 100644 --- a/composer.json +++ b/composer.json @@ -175,8 +175,8 @@ "codeception/module-symfony": "^1.6.0", "codeception/phpunit-wrapper": "^9", "pimcore/elasticsearch-client": "^1.0.0", - "phpstan/phpstan": "^1.9.3", - "phpstan/phpstan-symfony": "^1.2.14", + "phpstan/phpstan": "^1.9.5", + "phpstan/phpstan-symfony": "^1.2.19", "phpunit/phpunit": "^9.3", "spiritix/php-chrome-html2pdf": "^1.6", "elasticsearch/elasticsearch": "^8.0", diff --git a/doc/Development_Documentation/07_Workflow_Management/01_Configuration_Details/README.md b/doc/Development_Documentation/07_Workflow_Management/01_Configuration_Details/README.md index 2bd98b66af3..5487f9c82f5 100644 --- a/doc/Development_Documentation/07_Workflow_Management/01_Configuration_Details/README.md +++ b/doc/Development_Documentation/07_Workflow_Management/01_Configuration_Details/README.md @@ -284,7 +284,7 @@ pimcore: objectLayout: false # An expression to block the action - guard: ~ # Example: is_fully_authenticated() and has_role('ROLE_JOURNALIST') and subject.getTitle() == 'My first article' + guard: ~ # Example: is_fully_authenticated() and is_granted('ROLE_JOURNALIST') and subject.getTitle() == 'My first article' # Optionally set the current place of the workflow. Can be used for example to reset the workflow to the initial place. to: [] diff --git a/doc/Development_Documentation/18_Tools_and_Features/README.md b/doc/Development_Documentation/18_Tools_and_Features/README.md index f300d79e722..c3e40dcf326 100644 --- a/doc/Development_Documentation/18_Tools_and_Features/README.md +++ b/doc/Development_Documentation/18_Tools_and_Features/README.md @@ -4,7 +4,7 @@ This section of documentation gives an overview over tools and features provided be used via Pimcore PHP API. The topics include insights to [Versioning](./01_Versioning.md), [Notes and Events](./05_Notes_and_Events.md), -[Tags](./05_Tags.md), [Perspectives](./13_Perspectives.md) and much much more. +[Tags](./09_Tags.md), [Perspectives](./13_Perspectives.md) and much much more. Just have a look at the sub pages and dive into the possibilities of Pimcore. diff --git a/lib/Tool/Text/Csv.php b/lib/Tool/Text/Csv.php index 5a929337a29..d1cba0d9cff 100644 --- a/lib/Tool/Text/Csv.php +++ b/lib/Tool/Text/Csv.php @@ -135,6 +135,8 @@ protected function guessQuoteAndDelim($data) * @param string $quotechar * * @return bool|string + * + * @phpstan-param non-empty-string $linefeed */ protected function guessDelim($data, $linefeed, $quotechar) { diff --git a/models/Asset.php b/models/Asset.php index f4cea62be50..8102cdc5f0c 100644 --- a/models/Asset.php +++ b/models/Asset.php @@ -442,7 +442,7 @@ public static function getTypeFromMimeMapping($mimeType, $filename) $mappings = [ 'unknown' => ["/\.stp$/"], 'image' => ['/image/', "/\.eps$/", "/\.ai$/", "/\.svgz$/", "/\.pcx$/", "/\.iff$/", "/\.pct$/", "/\.wmf$/", '/photoshop/'], - 'text' => ['/text/', '/xml$/', '/\.json$/'], + 'text' => ['/text\//', '/xml$/', '/\.json$/'], 'audio' => ['/audio/'], 'video' => ['/video/'], 'document' => ['/msword/', '/pdf/', '/powerpoint/', '/office/', '/excel/', '/opendocument/'], diff --git a/models/Asset/Folder.php b/models/Asset/Folder.php index 3fcb0149308..b83d73b2ee5 100644 --- a/models/Asset/Folder.php +++ b/models/Asset/Folder.php @@ -183,7 +183,13 @@ public function getPreviewImage(bool $force = false) break; } - $tile = imagecreatefromstring(stream_get_contents($tileThumb->getStream())); + $stream = $tileThumb->getStream(); + + if (null === $stream) { + break; + } + + $tile = imagecreatefromstring(stream_get_contents($stream)); imagecopyresampled($collage, $tile, $offsetLeft, $offsetTop, 0, 0, $squareDimension, $squareDimension, $tileThumb->getWidth(), $tileThumb->getHeight()); $count++; diff --git a/models/DataObject/ClassDefinition/Data/QuantityValue.php b/models/DataObject/ClassDefinition/Data/QuantityValue.php index bdf5049677b..6254317e23d 100644 --- a/models/DataObject/ClassDefinition/Data/QuantityValue.php +++ b/models/DataObject/ClassDefinition/Data/QuantityValue.php @@ -531,13 +531,16 @@ public function getDataForResource($data, $object = null, $params = []) */ public function getDataFromResource($data, $object = null, $params = []) { - if ($data[$this->getName() . '__value'] !== null || $data[$this->getName() . '__unit']) { - if (!is_numeric($data[$this->getName() . '__value'])) { - $value = $this->toNumeric($data[$this->getName() . '__value']); + $dataValue = $data[$this->getName() . '__value']; + $dataUnit = $data[$this->getName() . '__unit']; + + if ($dataValue !== null || $dataUnit) { + if ($dataValue !== null && !is_numeric($dataValue)) { + $value = $this->toNumeric($dataValue); } else { - $value = $data[$this->getName() . '__value']; + $value = $dataValue; } - $quantityValue = new Model\DataObject\Data\QuantityValue((float) $value, $data[$this->getName() . '__unit']); + $quantityValue = new Model\DataObject\Data\QuantityValue($value === null ? null : (float)$value, $dataUnit); if (isset($params['owner'])) { $quantityValue->_setOwner($params['owner']); diff --git a/models/DataObject/ClassDefinition/Service.php b/models/DataObject/ClassDefinition/Service.php index 9b6f6918aae..68126184116 100644 --- a/models/DataObject/ClassDefinition/Service.php +++ b/models/DataObject/ClassDefinition/Service.php @@ -341,6 +341,11 @@ public static function importObjectBrickFromJson($objectBrick, $json, $throwExce public static function generateLayoutTreeFromArray($array, $throwException = false, $insideLocalizedField = false) { if (is_array($array) && count($array) > 0) { + if ($title = $array['title'] ?? false) { + if (preg_match('/<.+?>/', $title)) { + throw new \Exception('not a valid title:' . htmlentities($title)); + } + } if ($name = $array['name'] ?? false) { if (preg_match('/<.+?>/', $name)) { throw new \Exception('not a valid name:' . htmlentities($name)); diff --git a/models/DataObject/Fieldcollection.php b/models/DataObject/Fieldcollection.php index e9cdb99bafa..8651dee8490 100644 --- a/models/DataObject/Fieldcollection.php +++ b/models/DataObject/Fieldcollection.php @@ -15,6 +15,7 @@ namespace Pimcore\Model\DataObject; +use Pimcore\Logger; use Pimcore\Model; use Pimcore\Model\DataObject; use Pimcore\Model\Element\DirtyIndicatorInterface; @@ -33,7 +34,7 @@ class Fieldcollection extends Model\AbstractModel implements \Iterator, DirtyInd /** * @internal * - * @var TItem[] + * @var array */ protected $items = []; @@ -366,4 +367,16 @@ public function loadLazyData() } } } + + public function __wakeup() + { + if (is_array($this->items)) { + foreach ($this->items as $key => $item) { + if ($item instanceof \__PHP_Incomplete_Class) { + unset($this->items[$key]); + Logger::error('fieldcollection item ' . $key . ' does not exist anymore'); + } + } + } + } } diff --git a/models/DataObject/Objectbrick.php b/models/DataObject/Objectbrick.php index 924d5f83e1a..639b2e4f7ff 100644 --- a/models/DataObject/Objectbrick.php +++ b/models/DataObject/Objectbrick.php @@ -319,8 +319,6 @@ public function __sleep(): array public function __wakeup() { - $brickGetter = null; - // for backwards compatibility if ($this->object) { $this->objectId = $this->object->getId(); @@ -339,7 +337,7 @@ public function __wakeup() foreach ($this->items as $key => $item) { if ($item instanceof \__PHP_Incomplete_Class) { unset($this->items[$key]); - Logger::error('brick ' . $brickGetter . ' does not exist anymore'); + Logger::error('brick item ' . $key . ' does not exist anymore'); } } } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 7313a8490a9..9da48d5a3c5 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -190,11 +190,6 @@ parameters: count: 1 path: lib/Tool/Serialize.php - - - message: "#^Parameter \\#1 \\$separator of function explode expects non\\-empty\\-string, string given\\.$#" - count: 1 - path: lib/Tool/Text/Csv.php - - message: "#^Negated boolean expression is always true\\.$#" count: 1