Merge branch '5.1'
* 5.1: [PhpUnitBridge] Create a predictable symlink pointing to the local install [PropertyInfo] Backport support for typed properties (PHP 7.4) [PhpUnitBridge] Polyfill new phpunit 9.1 assertions [PhpUnitBridge] Move assertMatchesRegularExpression in PolyfillAssertTrait [PhpUnit] Add polyfill for assertMatchesRegularExpression() Update Notifier bridge readme [TwigBridge] Fix #37931: BC break where filter method `trans` did not allow null values for `$message` parameter anymore [PropertyAccess] Fix accessing dynamic properties
This commit is contained in:
commit
5b3ebdc7e6
@ -13,6 +13,7 @@ namespace Symfony\Bridge\PhpUnit\Legacy;
|
||||
|
||||
use PHPUnit\Framework\Constraint\IsEqual;
|
||||
use PHPUnit\Framework\Constraint\LogicalNot;
|
||||
use PHPUnit\Framework\Constraint\RegularExpression;
|
||||
use PHPUnit\Framework\Constraint\StringContains;
|
||||
use PHPUnit\Framework\Constraint\TraversableContains;
|
||||
|
||||
|
@ -284,6 +284,16 @@ EOPHP
|
||||
chdir($oldPwd);
|
||||
}
|
||||
|
||||
// Create a symlink with a predictable path pointing to the currently used version.
|
||||
// This is useful for static analytics tools such as PHPStan having to load PHPUnit's classes
|
||||
// and for other testing libraries such as Behat using PHPUnit's assertions.
|
||||
chdir($PHPUNIT_DIR);
|
||||
if (file_exists('phpunit')) {
|
||||
@unlink('phpunit');
|
||||
}
|
||||
@symlink($PHPUNIT_VERSION_DIR, 'phpunit');
|
||||
chdir($oldPwd);
|
||||
|
||||
if ($PHPUNIT_VERSION < 8.0) {
|
||||
$argv = array_filter($argv, function ($v) use (&$argc) {
|
||||
if ('--do-not-cache-result' !== $v) {
|
||||
|
@ -91,8 +91,12 @@ final class TranslationExtension extends AbstractExtension
|
||||
return $this->translationNodeVisitor ?: $this->translationNodeVisitor = new TranslationNodeVisitor();
|
||||
}
|
||||
|
||||
public function trans(string $message, array $arguments = [], string $domain = null, string $locale = null, int $count = null): string
|
||||
public function trans(?string $message, array $arguments = [], string $domain = null, string $locale = null, int $count = null): string
|
||||
{
|
||||
if (null === $message || '' === $message) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (null !== $count) {
|
||||
$arguments['%count%'] = $count;
|
||||
}
|
||||
|
@ -118,6 +118,10 @@ class TranslationExtensionTest extends TestCase
|
||||
['{{ "{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples"|trans(count=count) }}', 'There is 5 apples', ['count' => 5]],
|
||||
['{{ text|trans(count=5, arguments={\'%name%\': \'Symfony\'}) }}', 'There is 5 apples (Symfony)', ['text' => '{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%)']],
|
||||
['{{ "{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples"|trans({}, "messages", "fr", count) }}', 'There is 5 apples', ['count' => 5]],
|
||||
|
||||
// trans filter with null message
|
||||
['{{ null|trans }}', ''],
|
||||
['{{ foo|trans }}', '', ['foo' => null]],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,18 @@ Firebase Notifier
|
||||
|
||||
Provides Firebase integration for Symfony Notifier.
|
||||
|
||||
DSN example
|
||||
-----------
|
||||
|
||||
```
|
||||
// .env file
|
||||
FIREBASE_DSN=firebase://USERNAME:PASSWORD@default
|
||||
```
|
||||
|
||||
where:
|
||||
- `USERNAME` is your Firebase username
|
||||
- `PASSWORD` is your Firebase password
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
|
@ -3,6 +3,18 @@ Mattermost Notifier
|
||||
|
||||
Provides Mattermost integration for Symfony Notifier.
|
||||
|
||||
DSN example
|
||||
-----------
|
||||
|
||||
```
|
||||
// .env file
|
||||
MATTERMOST_DSN=mattermost://ACCESS_TOKEN@default?channel=CHANNEL
|
||||
```
|
||||
|
||||
where:
|
||||
- `ACCESS_TOKEN` is your Mattermost access token
|
||||
- `CHANNEL` is your Mattermost channel
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
|
@ -3,6 +3,18 @@ RocketChat Notifier
|
||||
|
||||
Provides RocketChat integration for Symfony Notifier.
|
||||
|
||||
DSN example
|
||||
-----------
|
||||
|
||||
```
|
||||
// .env file
|
||||
ROCKETCHAT_DSN=rocketchat://ACCESS_TOKEN@default?channel=CHANNEL
|
||||
```
|
||||
|
||||
where:
|
||||
- `ACCESS_TOKEN` is your RocketChat access token
|
||||
- `CHANNEL` is your RocketChat channel
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
|
@ -3,6 +3,19 @@ Sinch Notifier
|
||||
|
||||
Provides Sinch integration for Symfony Notifier.
|
||||
|
||||
DSN example
|
||||
-----------
|
||||
|
||||
```
|
||||
// .env file
|
||||
SINCH_DSN=sinch://SERVICE_PLAN_ID:AUTH_TOKEN@default?from=FROM
|
||||
```
|
||||
|
||||
where:
|
||||
- `SERVICE_PLAN_ID` is your Sinch service plan id
|
||||
- `AUTH_TOKEN` is your Sinch auth token
|
||||
- `FROM` is your sender
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
|
@ -450,11 +450,17 @@ class PropertyAccessor implements PropertyAccessorInterface
|
||||
|
||||
throw $e;
|
||||
}
|
||||
} elseif ($object instanceof \stdClass && property_exists($object, $property)) {
|
||||
} elseif (property_exists($object, $property)) {
|
||||
try {
|
||||
$result[self::VALUE] = $object->$property;
|
||||
if (isset($zval[self::REF])) {
|
||||
$result[self::REF] = &$object->$property;
|
||||
}
|
||||
} catch (\Error $e) {
|
||||
if (!$ignoreInvalidProperty) {
|
||||
throw new NoSuchPropertyException(sprintf('Can\'t read protected or private property "%s" in class "%s".', $property, $class), 0, $e);
|
||||
}
|
||||
}
|
||||
} elseif (!$ignoreInvalidProperty) {
|
||||
throw new NoSuchPropertyException(sprintf('Can\'t get a way to read the property "%s" in class "%s".', $property, $class));
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\PropertyAccess\Tests\Fixtures;
|
||||
|
||||
class TestClassDynamicProperty
|
||||
{
|
||||
public function __construct($dynamicProperty)
|
||||
{
|
||||
$this->dynamicProperty = $dynamicProperty;
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ use Symfony\Component\PropertyAccess\Tests\Fixtures\ReturnTyped;
|
||||
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestAdderRemoverInvalidArgumentLength;
|
||||
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestAdderRemoverInvalidMethods;
|
||||
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClass;
|
||||
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassDynamicProperty;
|
||||
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassIsWritable;
|
||||
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicCall;
|
||||
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicGet;
|
||||
@ -98,6 +99,29 @@ class PropertyAccessorTest extends TestCase
|
||||
$this->assertSame($value, $this->propertyAccessor->getValue($objectOrArray, $path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get dynamic value from object is other than \stdClass instance.
|
||||
*/
|
||||
public function testGetDynamicValue()
|
||||
{
|
||||
$value = 'dynamicPropertyValue';
|
||||
$path = 'dynamicProperty';
|
||||
$object = new TestClassDynamicProperty($value);
|
||||
|
||||
$this->assertSame($value, $this->propertyAccessor->getValue($object, $path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure exact exception with message was thrown on access to non-public property.
|
||||
*/
|
||||
public function testGetInaccessibleProperty()
|
||||
{
|
||||
$this->expectException('Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException');
|
||||
$this->expectExceptionMessage(sprintf('Can\'t read protected or private property "%s" in class "%s".', 'protectedProperty', TestClass::class));
|
||||
|
||||
$this->propertyAccessor->getValue(new TestClass('Bernhard'), 'protectedProperty');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getPathsWithMissingProperty
|
||||
*/
|
||||
|
Reference in New Issue
Block a user