Compare commits

..

50 Commits

Author SHA1 Message Date
Benjamin Eberlei 445796af0e Travis: Use 7.4 instead of 7.4snapshot 2020-02-15 15:35:56 +01:00
Benjamin Eberlei ab93285284 Remove nightly builds from .travis.yml 2020-02-15 15:34:36 +01:00
Benjamin Eberlei a692670469 Merge pull request #8006 from doctrine/malarzm-patch-1
Make Embeddable not transient
2020-02-13 21:31:02 +01:00
Maciej Malarz 58677c29b4 Make Embeddable not transient 2020-02-13 21:05:52 +01:00
Benjamin Eberlei 9a0fcb5a86 Merge pull request #7940 from doctrine/GH-7864-ExtraLazyRemoveElement
[GH-7864] Bugfix in PersistentCollection::removeElement for EXTRA_LAZY.
2020-02-12 23:42:06 +01:00
Benjamin Eberlei 8104c65d6c Merge pull request #7987 from beberlei/GH-7982-NoSqlExecutor
[GH-7982] no sql executor leads to parse error
2020-02-12 23:37:39 +01:00
Benjamin Eberlei a64d254d07 [GH-7982] Bugfix: Passing string|null DQL to Lexer(string $input) leads to downstream notice. 2020-02-12 23:23:12 +01:00
Benjamin Eberlei fdad48278b Merge pull request #7991 from greg0ire/7.4-sa
Try running phpstan on php 7.4
2020-01-17 00:06:40 +01:00
Benjamin Eberlei fc94127d7f Make ocramius/package-versions 1.2 the lowest version for phpstan 2020-01-16 23:51:17 +01:00
Grégoire Paris dea3e5df44 Try running phpstan on php 7.4
It might be easier to find packages compatible with both our locked deps
and phpstan with that version of php.
2020-01-16 23:49:15 +01:00
Benjamin Eberlei 5d7d3e99a0 Downgrade ocramius/package-versions to lowest in composer.lock to support all PHP versions. 2020-01-16 23:18:00 +01:00
Benjamin Eberlei 3bc1096fd0 [GH-7982] Default Query state to dirty to fix execution of empty query. 2020-01-15 23:30:59 +01:00
Benjamin Eberlei a2f01f7ccc Allow everything from ocramius/package-versions ^1.0. 2020-01-15 22:56:08 +01:00
Benjamin Eberlei 401db453a2 Merge pull request #7974 from beberlei/gh-7505
[GH-7505] Bug in SimpleObjectHydrator when using inheritance with same field
2020-01-15 22:02:25 +01:00
Benjamin Eberlei 6e59ec8f16 [GH-7505] Fix cs 2020-01-15 21:52:11 +01:00
Benjamin Eberlei 87e491465a Add @group 2020-01-15 21:13:25 +01:00
Luís Cobucci 8b588eceb2 Merge pull request #7973 from DocFX/patch-1
Just a micro grammar update.
2020-01-14 11:26:21 +01:00
Benjamin Eberlei edce36598f Adjust tests back for 2.x. 2020-01-09 00:41:47 +01:00
Woody Gilk 20c46035d1 [Docs] Prefer PhpFileCache for caching and remove APC/XCache. 2020-01-08 19:36:08 +01:00
William Pinaud 324aacfb54 Just a micro grammar update. 2020-01-08 18:52:11 +01:00
Benjamin Eberlei 1edfcabead Merge pull request #7894 from TomckySan/convert-default-value-to-boolean
Fix boolean properties default value when generating entities.
2020-01-05 16:11:33 +01:00
Luís Cobucci 2785cde792 Merge pull request #7957 from lcobucci/fix-version-information
Fix version information
2019-12-17 19:19:05 +01:00
Luís Cobucci d67e3e8b1b Rely on ocramius/package-versions to render the version
Since `Doctrine\ORM\Version` is now deprecated it shall not be updated
on future releases.

This ensures that our CLI tool will present the correct version number.
2019-12-17 15:47:55 +01:00
Luís Cobucci d629c4e487 Remove build.xml and related files
We aren't using ant/phing to handle the releases any more.
2019-12-17 01:03:34 +01:00
Luís Cobucci 4a4226213f Merge pull request #7875 from nicolas-grekas/schema-tool
Whilelist existing assets we know about from metadata in SchemaTool::getUpdateSchemaSql()
2019-12-16 23:59:31 +01:00
Andreas Braun 0ce1440884 Add upgrade note about schema_filter change 2019-12-16 23:45:49 +01:00
Laurent VOULLEMIER 9aa28b4e33 Test asset whitelisting on SchemaTool#getUpdateSchemasSql() 2019-12-16 23:45:49 +01:00
Nicolas Grekas 5c2b6870bf Whitelist existing assets we know about from metadata in SchemaTool::getUpdateSchemaSql() 2019-12-16 23:22:50 +01:00
Luís Cobucci 4389b2c188 Merge pull request #7956 from lcobucci/fix-test-suite
Ignore Doctrine\Common\Persistence\ObjectManagerDecorator deprecation
2019-12-16 21:49:25 +01:00
Luís Cobucci e481d9880b Ignore Doctrine\Common\Persistence\ObjectManagerDecorator deprecation
Since applying the fixes requires bumping up the dependency, which isn't
done in a patch release.

This should be removed in v2.8.0.
2019-12-16 21:22:28 +01:00
Luís Cobucci 85528f28e2 Fix CS errors 2019-12-16 21:22:23 +01:00
Luís Cobucci 5873242fb5 Merge pull request #7937 from doctrine/GH-7930-SqliteForeignKeys
Revert SchemaTool change to check for foreign key support
2019-12-16 10:45:07 +01:00
Luís Cobucci c9e41d0aa7 Merge pull request #7934 from BenMorel/php74
Fix Trying to access array offset on value of type null
2019-12-09 21:32:58 +01:00
Benjamin Morel f37c12834d Fix Trying to access array offset on value of type null 2019-12-09 21:24:29 +01:00
Benjamin Eberlei 041404e8b3 [GH-7864] Revert removeElement EXTRA_LAZY support. 2019-12-07 00:03:09 +01:00
Benjamin Eberlei bfc68b3aba Add warning about removeElement on extra lazy 2019-12-03 20:34:44 +01:00
Benjamin Eberlei 1e628370c4 [GH-7864] Address review comments. 2019-12-03 19:35:49 +01:00
Benjamin Eberlei ae2b9b1921 Housekeeping: phpcbf to fix issues. 2019-12-01 21:11:09 +01:00
Benjamin Eberlei 419df77a09 [GH-7864] ExtraLazyCollectionTest is not cacahble and should not fail SLC suite. 2019-12-01 20:28:30 +01:00
Benjamin Eberlei d6f6b2e97c [GH-7864] Remove tests that checked invalid behavior. 2019-12-01 19:47:58 +01:00
Benjamin Eberlei 75d5adf599 [GH-7864] Bugfix in PersistentCollection::removeElement for EXTRA_LAZY. 2019-12-01 19:27:45 +01:00
Benjamin Eberlei cfd6fadf9c Revert "#7841 SchemaTool generates extra diff for platforms without FK support"
This reverts commit 3707c39124.
2019-12-01 11:23:45 +01:00
Tomoka Baba 2bf7916c52 Fix to pass code quality check. 2019-11-20 17:03:34 +09:00
Tomoka Baba 253fd10cc0 Modified test to use assertTrue. 2019-11-20 17:02:25 +09:00
Tomoka Baba 2c956d55f2 Fix to pass code quality check. 2019-11-20 17:02:25 +09:00
Tomoka Baba 3db992e953 Add test code. 2019-11-20 17:01:52 +09:00
Tomoka Baba 6fc9b3ab16 Fix to pass code quality check. 2019-11-20 17:01:52 +09:00
Tomoka Baba 2d833a5e86 Fix boolean properties default value when generating entities. 2019-11-20 17:01:19 +09:00
Luís Cobucci a416a9a8b2 Bump up version 2019-11-19 09:43:57 +01:00
Mickaël RAYBAUD-ROIG 3a32c00dcf Add a failing test for issue #7505 2019-11-14 23:28:42 +01:00
39 changed files with 726 additions and 930 deletions
+4 -5
View File
@@ -6,8 +6,7 @@ php:
- 7.1
- 7.2
- 7.3
- 7.4snapshot
- nightly
- 7.4
env:
- DB=sqlite
@@ -55,7 +54,7 @@ jobs:
- stage: Test
dist: xenial
env: DB=mysql MYSQL_VERSION=5.7
php: 7.4snapshot
php: 7.4
services:
- mysql
before_script:
@@ -87,6 +86,7 @@ jobs:
- stage: Code Quality
env: DB=none STATIC_ANALYSIS
php: 7.4
install: travis_retry composer install --prefer-dist
before_script:
- echo "extension=memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
@@ -102,7 +102,7 @@ jobs:
- stage: Code Quality
if: NOT type = pull_request
env: DB=none CODING_STANDARDS
php: 7.4snapshot
php: 7.4
install: travis_retry composer install --prefer-dist
script:
- ./vendor/bin/phpcs
@@ -123,7 +123,6 @@ jobs:
- php git-phpcs.phar origin/$TRAVIS_BRANCH...$TRAVIS_PULL_REQUEST_SHA
allow_failures:
- php: nightly
- stage: Code Quality
env: DB=none CODING_STANDARDS
+6
View File
@@ -10,6 +10,12 @@ Method `Doctrine\ORM\AbstractQuery#useResultCache()` which could be used for bot
To optimize DB interaction, `Doctrine\ORM\Tools\Pagination\Paginator` no longer fetches identifiers to be able to
perform the pagination with join collections when max results isn't set in the query.
## Minor BC BREAK: tables filtered with `schema_filter` are no longer created
When generating schema diffs, if a source table is filtered out by a `schema_filter` expression, then a `CREATE TABLE` was
always generated, even if the table already existed. This has been changed in this release and the table will no longer
be created.
## Deprecated number unaware `Doctrine\ORM\Mapping\UnderscoreNamingStrategy`
In the last patch of the `v2.6.x` series, we fixed a bug that was not converting names properly when they had numbers
-3
View File
@@ -1,3 +0,0 @@
# Version class and file
project.version_class = Doctrine\\ORM\\Version
project.version_file = lib/Doctrine/ORM/Version.php
-16
View File
@@ -1,16 +0,0 @@
version=2.0.0BETA2
dependencies.common=2.0.0BETA4
dependencies.dbal=2.0.0BETA4
stability=beta
build.dir=build
dist.dir=dist
report.dir=reports
log.archive.dir=logs
project.pirum_dir=
project.download_dir=
project.xsd_dir=
test.phpunit_configuration_file=
test.phpunit_generate_coverage=0
test.pmd_reports=0
test.pdepend_exec=
test.phpmd_exec=
-101
View File
@@ -1,101 +0,0 @@
<?xml version="1.0"?>
<project name="DoctrineORM" default="build" basedir=".">
<property file="build.properties" />
<target name="php">
<exec executable="which" outputproperty="php_executable">
<arg value="php" />
</exec>
</target>
<target name="prepare">
<mkdir dir="build" />
</target>
<target name="build" depends="check-git-checkout-clean,prepare,php,composer">
<exec executable="${php_executable}">
<arg value="build/composer.phar" />
<arg value="archive" />
<arg value="--dir=build" />
</exec>
</target>
<target name="composer" depends="php,composer-check,composer-download">
<exec executable="${php_executable}">
<arg value="build/composer.phar" />
<arg value="install" />
</exec>
</target>
<target name="composer-check" depends="prepare">
<available file="build/composer.phar" property="composer.present"/>
</target>
<target name="composer-download" unless="composer.present">
<exec executable="wget">
<arg value="-Obuild/composer.phar" />
<arg value="http://getcomposer.org/composer.phar" />
</exec>
</target>
<target name="make-release" depends="check-git-checkout-clean,prepare,php">
<replace file="${project.version_file}" token="-DEV" value="" failOnNoReplacements="true" />
<exec executable="${php_executable}" outputproperty="doctrine.current_version" failonerror="true">
<arg value="-r" />
<arg value="require_once '${project.version_file}';echo ${project.version_class}::VERSION;" />
</exec>
<exec executable="${php_executable}" outputproperty="doctrine.next_version" failonerror="true">
<arg value="-r" />
<arg value="$parts = explode('.', str_ireplace(array('-DEV', '-ALPHA', '-BETA'), '', '${doctrine.current_version}'));
if (count($parts) != 3) {
throw new \InvalidArgumentException('Version is assumed in format x.y.z, ${doctrine.current_version} given');
}
$parts[2]++;
echo implode('.', $parts);
" />
</exec>
<git-commit file="${project.version_file}" message="Release ${doctrine.current_version}" />
<git-tag version="${doctrine.current_version}" />
<replace file="${project.version_file}" token="${doctrine.current_version}" value="${doctrine.next_version}-DEV" />
<git-commit file="${project.version_file}" message="Bump version to ${doctrine.next_version}" />
</target>
<target name="check-git-checkout-clean">
<exec executable="git" failonerror="true">
<arg value="diff-index" />
<arg value="--quiet" />
<arg value="HEAD" />
</exec>
</target>
<macrodef name="git-commit">
<attribute name="file" default="NOT SET"/>
<attribute name="message" default="NOT SET"/>
<sequential>
<exec executable="git">
<arg value="add" />
<arg value="@{file}" />
</exec>
<exec executable="git">
<arg value="commit" />
<arg value="-m" />
<arg value="@{message}" />
</exec>
</sequential>
</macrodef>
<macrodef name="git-tag">
<attribute name="version" default="NOT SET" />
<sequential>
<exec executable="git">
<arg value="tag" />
<arg value="-m" />
<arg value="v@{version}" />
<arg value="v@{version}" />
</exec>
</sequential>
</macrodef>
</project>
+1
View File
@@ -26,6 +26,7 @@
"doctrine/event-manager": "^1.1",
"doctrine/instantiator": "^1.3",
"doctrine/persistence": "^1.2",
"ocramius/package-versions": "^1.2",
"symfony/console": "^3.0|^4.0|^5.0"
},
"require-dev": {
Generated
+51 -2
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4e24e01f599825550170acce0dda0b49",
"content-hash": "22be7b4b42da2931c1033f8818a0caa9",
"packages": [
{
"name": "doctrine/annotations",
@@ -805,6 +805,55 @@
],
"time": "2018-06-14T14:45:07+00:00"
},
{
"name": "ocramius/package-versions",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/Ocramius/PackageVersions.git",
"reference": "ad8a245decad4897cc6b432743913dad0d69753c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/ad8a245decad4897cc6b432743913dad0d69753c",
"reference": "ad8a245decad4897cc6b432743913dad0d69753c",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0",
"php": "~7.0"
},
"require-dev": {
"composer/composer": "^1.3",
"ext-zip": "*",
"humbug/humbug": "dev-master",
"phpunit/phpunit": "^6.4"
},
"type": "composer-plugin",
"extra": {
"class": "PackageVersions\\Installer",
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"PackageVersions\\": "src/PackageVersions"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com"
}
],
"description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
"time": "2017-11-24T11:07:03+00:00"
},
{
"name": "psr/log",
"version": "1.1.2",
@@ -2735,7 +2784,7 @@
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"prefer-lowest": true,
"platform": {
"php": "^7.1",
"ext-pdo": "*"
+1 -1
View File
@@ -99,7 +99,7 @@ Optional attributes:
- **length**: Used by the "string" type to determine its maximum
length in the database. Doctrine does not validate the length of a
string values for you.
string value for you.
- **precision**: The precision for a decimal (exact numeric) column
(applies only for decimal column), which is the maximum number of
+40 -49
View File
@@ -45,41 +45,29 @@ This documentation does not cover every single cache driver included
with Doctrine. For an up-to-date-list, see the
`cache directory on GitHub <https://github.com/doctrine/cache/tree/master/lib/Doctrine/Common/Cache>`_.
APC
~~~
PhpFileCache
~~~~~~~~~~~~
In order to use the APC cache driver you must have it compiled and
enabled in your php.ini. You can read about APC
`in the PHP Documentation <http://us2.php.net/apc>`_. It will give
you a little background information about what it is and how you
can use it as well as how to install it.
The preferred cache driver for metadata and query caches is ``PhpFileCache``.
This driver serializes cache items and writes them to a file. This allows for
opcode caching to be used and provides high performance in most scenarios.
Below is a simple example of how you could use the APC cache driver
by itself.
In order to use the ``PhpFileCache`` driver it must be able to write to
a directory.
Below is an example of how to use the ``PhpFileCache`` driver by itself.
.. code-block:: php
<?php
$cacheDriver = new \Doctrine\Common\Cache\ApcCache();
$cacheDriver = new \Doctrine\Common\Cache\PhpFileCache(
'/path/to/writable/directory'
);
$cacheDriver->save('cache_id', 'my_data');
APCu
~~~~
In order to use the APCu cache driver you must have it compiled and
enabled in your php.ini. You can read about APCu
`in the PHP Documentation <http://us2.php.net/apcu>`_. It will give
you a little background information about what it is and how you
can use it as well as how to install it.
Below is a simple example of how you could use the APCu cache driver
by itself.
.. code-block:: php
<?php
$cacheDriver = new \Doctrine\Common\Cache\ApcuCache();
$cacheDriver->save('cache_id', 'my_data');
The PhpFileCache is not distributed across multiple machines if you are running
your application in a distributed setup. This is ok for the metadata and query
cache but is not a good approach for the result cache.
Memcache
~~~~~~~~
@@ -128,24 +116,6 @@ driver by itself.
$cacheDriver->setMemcached($memcached);
$cacheDriver->save('cache_id', 'my_data');
Xcache
~~~~~~
In order to use the Xcache cache driver you must have it compiled
and enabled in your php.ini. You can read about Xcache
`here <http://xcache.lighttpd.net/>`_. It will give you a little
background information about what it is and how you can use it as
well as how to install it.
Below is a simple example of how you could use the Xcache cache
driver by itself.
.. code-block:: php
<?php
$cacheDriver = new \Doctrine\Common\Cache\XcacheCache();
$cacheDriver->save('cache_id', 'my_data');
Redis
~~~~~
@@ -306,8 +276,11 @@ use on your ORM configuration.
.. code-block:: php
<?php
$cacheDriver = new \Doctrine\Common\Cache\PhpFileCache(
'/path/to/writable/directory'
);
$config = new \Doctrine\ORM\Configuration();
$config->setQueryCacheImpl(new \Doctrine\Common\Cache\ApcuCache());
$config->setQueryCacheImpl($cacheDriver);
Result Cache
~~~~~~~~~~~~
@@ -320,7 +293,11 @@ cache implementation.
.. code-block:: php
<?php
$config->setResultCacheImpl(new \Doctrine\Common\Cache\ApcuCache());
$cacheDriver = new \Doctrine\Common\Cache\PhpFileCache(
'/path/to/writable/directory'
);
$config = new \Doctrine\ORM\Configuration();
$config->setResultCacheImpl($cacheDriver);
Now when you're executing DQL queries you can configure them to use
the result cache.
@@ -337,7 +314,11 @@ result cache driver.
.. code-block:: php
<?php
$query->setResultCacheDriver(new \Doctrine\Common\Cache\ApcuCache());
$cacheDriver = new \Doctrine\Common\Cache\PhpFileCache(
'/path/to/writable/directory'
);
$config = new \Doctrine\ORM\Configuration();
$query->setResultCacheDriver($cacheDriver);
.. note::
@@ -389,7 +370,11 @@ first.
.. code-block:: php
<?php
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ApcuCache());
$cacheDriver = new \Doctrine\Common\Cache\PhpFileCache(
'/path/to/writable/directory'
);
$config = new \Doctrine\ORM\Configuration();
$config->setMetadataCacheImpl($cacheDriver);
Now the metadata information will only be parsed once and stored in
the cache driver.
@@ -425,6 +410,12 @@ To clear the result cache use the ``orm:clear-cache:result`` task.
All these tasks accept a ``--flush`` option to flush the entire
contents of the cache instead of invalidating the entries.
.. note::
None of these tasks will work with APC, APCu, or XCache drivers
because the memory that the cache is stored in is only accessible
to the webserver.
Cache Chaining
--------------
@@ -35,6 +35,15 @@ With extra lazy collections you can now not only add entities to large collectio
easily using a combination of ``count`` and ``slice``.
.. warning::
``removeElement`` directly issued DELETE queries to the database from
version 2.4.0 to 2.7.0. This circumvents the flush operation and might run
outside a transactional boundary if you don't create one yourself. We
consider this a critical bug in the assumptio of how the ORM works and
reverted ``removeElement`` EXTRA_LAZY behavior in 2.7.1.
Enabling Extra-Lazy Associations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -243,20 +243,6 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
return $this->persister->get($collection, $index);
}
/**
* {@inheritdoc}
*/
public function removeElement(PersistentCollection $collection, $element)
{
if ($persisterResult = $this->persister->removeElement($collection, $element)) {
$this->evictCollectionCache($collection);
$this->evictElementCache($this->sourceEntity->rootEntityName, $collection->getOwner());
$this->evictElementCache($this->targetEntity->rootEntityName, $element);
}
return $persisterResult;
}
/**
* {@inheritdoc}
*/
@@ -22,6 +22,7 @@ namespace Doctrine\ORM\Internal\Hydration;
use PDO;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query;
use function in_array;
class SimpleObjectHydrator extends AbstractHydrator
{
@@ -78,8 +79,9 @@ class SimpleObjectHydrator extends AbstractHydrator
*/
protected function hydrateRowData(array $sqlResult, array &$result)
{
$entityName = $this->class->name;
$data = [];
$entityName = $this->class->name;
$data = [];
$discrColumnValue = null;
// We need to find the correct entity class name if we have inheritance in resultset
if ($this->class->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) {
@@ -104,7 +106,8 @@ class SimpleObjectHydrator extends AbstractHydrator
throw HydrationException::invalidDiscriminatorValue($sqlResult[$discrColumnName], array_keys($discrMap));
}
$entityName = $discrMap[$sqlResult[$discrColumnName]];
$entityName = $discrMap[$sqlResult[$discrColumnName]];
$discrColumnValue = $sqlResult[$discrColumnName];
unset($sqlResult[$discrColumnName]);
}
@@ -134,6 +137,11 @@ class SimpleObjectHydrator extends AbstractHydrator
// Prevent overwrite in case of inherit classes using same property name (See AbstractHydrator)
if ( ! isset($data[$fieldName]) || ! $valueIsNull) {
// If we have inheritance in resultset, make sure the field belongs to the correct class
if (isset($cacheKeyInfo['discriminatorValues']) && ! in_array($discrColumnValue, $cacheKeyInfo['discriminatorValues'], true)) {
continue;
}
$data[$fieldName] = $value;
}
}
@@ -44,6 +44,7 @@ class AnnotationDriver extends AbstractAnnotationDriver
protected $entityAnnotationClasses = [
Mapping\Entity::class => 1,
Mapping\MappedSuperclass::class => 2,
Mapping\Embeddable::class => 3,
];
/**
-10
View File
@@ -367,16 +367,6 @@ final class PersistentCollection extends AbstractLazyCollection implements Selec
*/
public function removeElement($element)
{
if ( ! $this->initialized && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) {
if ($this->collection->contains($element)) {
return $this->collection->removeElement($element);
}
$persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association);
return $persister->removeElement($this, $element);
}
$removed = parent::removeElement($element);
if ( ! $removed) {
@@ -90,16 +90,6 @@ interface CollectionPersister
*/
public function containsKey(PersistentCollection $collection, $key);
/**
* Removes an element.
*
* @param \Doctrine\ORM\PersistentCollection $collection
* @param object $element
*
* @return mixed
*/
public function removeElement(PersistentCollection $collection, $element);
/**
* Gets an element by key.
*
@@ -211,22 +211,6 @@ class ManyToManyPersister extends AbstractCollectionPersister
return (bool) $this->conn->fetchColumn($sql, $params, 0, $types);
}
/**
* {@inheritDoc}
*/
public function removeElement(PersistentCollection $collection, $element)
{
if ( ! $this->isValidEntityState($element)) {
return false;
}
list($quotedJoinTable, $whereClauses, $params, $types) = $this->getJoinTableRestrictions($collection, $element, false);
$sql = 'DELETE FROM ' . $quotedJoinTable . ' WHERE ' . implode(' AND ', $whereClauses);
return (bool) $this->conn->executeUpdate($sql, $params, $types);
}
/**
* {@inheritDoc}
*/
@@ -166,28 +166,6 @@ class OneToManyPersister extends AbstractCollectionPersister
return $persister->exists($element, $criteria);
}
/**
* {@inheritdoc}
*/
public function removeElement(PersistentCollection $collection, $element)
{
$mapping = $collection->getMapping();
if ( ! $mapping['orphanRemoval']) {
// no-op: this is not the owning side, therefore no operations should be applied
return false;
}
if ( ! $this->isValidEntityState($element)) {
return false;
}
return $this
->uow
->getEntityPersister($mapping['targetEntity'])
->delete($element);
}
/**
* {@inheritdoc}
*/
+1 -1
View File
@@ -133,7 +133,7 @@ final class Query extends AbstractQuery
*
* @var integer
*/
private $_state = self::STATE_CLEAN;
private $_state = self::STATE_DIRTY;
/**
* A snapshot of the parameter types the query was parsed with.
+2 -2
View File
@@ -189,7 +189,7 @@ class Parser
{
$this->query = $query;
$this->em = $query->getEntityManager();
$this->lexer = new Lexer($query->getDQL());
$this->lexer = new Lexer((string) $query->getDQL());
$this->parserResult = new ParserResult();
}
@@ -302,7 +302,7 @@ class Parser
*/
public function match($token)
{
$lookaheadType = $this->lexer->lookahead['type'];
$lookaheadType = $this->lexer->lookahead['type'] ?? null;
// Short-circuit on first condition, usually types match
if ($lookaheadType === $token) {
@@ -22,7 +22,8 @@ namespace Doctrine\ORM\Tools\Console;
use Doctrine\DBAL\Tools\Console as DBALConsole;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;
use Doctrine\ORM\Version;
use OutOfBoundsException;
use PackageVersions\Versions;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Helper\HelperSet;
@@ -70,10 +71,11 @@ final class ConsoleRunner
* @param array $commands
*
* @return \Symfony\Component\Console\Application
* @throws OutOfBoundsException
*/
public static function createApplication(HelperSet $helperSet, array $commands = []) : Application
{
$cli = new Application('Doctrine Command Line Interface', Version::VERSION);
$cli = new Application('Doctrine Command Line Interface', Versions::getVersion('doctrine/orm'));
$cli->setCatchExceptions(true);
$cli->setHelperSet($helperSet);
self::addCommands($cli);
+11 -2
View File
@@ -26,6 +26,7 @@ use Doctrine\ORM\Mapping\ClassMetadataInfo;
use const E_USER_DEPRECATED;
use function str_replace;
use function trigger_error;
use function var_export;
/**
* Generic class used to generate PHP5 entity classes from ClassMetadataInfo instances.
@@ -1328,9 +1329,17 @@ public function __construct(<params>)
continue;
}
$defaultValue = '';
if (isset($fieldMapping['options']['default'])) {
if ($fieldMapping['type'] === 'boolean' && $fieldMapping['options']['default'] === '1') {
$defaultValue = ' = true';
} else {
$defaultValue = ' = ' . var_export($fieldMapping['options']['default'], true);
}
}
$lines[] = $this->generateFieldMappingPropertyDocBlock($fieldMapping, $metadata);
$lines[] = $this->spaces . $this->fieldVisibility . ' $' . $fieldMapping['fieldName']
. (isset($fieldMapping['options']['default']) ? ' = ' . var_export($fieldMapping['options']['default'], true) : null) . ";\n";
$lines[] = $this->spaces . $this->fieldVisibility . ' $' . $fieldMapping['fieldName'] . $defaultValue . ";\n";
}
return implode("\n", $lines);
+34 -9
View File
@@ -19,7 +19,7 @@
namespace Doctrine\ORM\Tools;
use Doctrine\ORM\ORMException;
use Doctrine\DBAL\Schema\AbstractAsset;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Schema;
@@ -28,6 +28,7 @@ use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector;
use Doctrine\DBAL\Schema\Visitor\RemoveNamespacedAssets;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\ORMException;
use Doctrine\ORM\Tools\Event\GenerateSchemaTableEventArgs;
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
@@ -709,11 +710,6 @@ class SchemaTool
}
$compositeName = $theJoinTable->getName().'.'.implode('', $localColumns);
if (! $this->platform->supportsForeignKeyConstraints()) {
return;
}
if (isset($addedFks[$compositeName])
&& ($foreignTableName != $addedFks[$compositeName]['foreignTableName']
|| 0 < count(array_diff($foreignColumns, $addedFks[$compositeName]['foreignColumns'])))
@@ -896,10 +892,8 @@ class SchemaTool
*/
public function getUpdateSchemaSql(array $classes, $saveMode = false)
{
$sm = $this->em->getConnection()->getSchemaManager();
$fromSchema = $sm->createSchema();
$toSchema = $this->getSchemaFromMetadata($classes);
$fromSchema = $this->createSchemaForComparison($toSchema);
$comparator = new Comparator();
$schemaDiff = $comparator->compare($fromSchema, $toSchema);
@@ -910,4 +904,35 @@ class SchemaTool
return $schemaDiff->toSql($this->platform);
}
/**
* Creates the schema from the database, ensuring tables from the target schema are whitelisted for comparison.
*/
private function createSchemaForComparison(Schema $toSchema) : Schema
{
$connection = $this->em->getConnection();
$schemaManager = $connection->getSchemaManager();
// backup schema assets filter
$config = $connection->getConfiguration();
$previousFilter = $config->getSchemaAssetsFilter();
if ($previousFilter === null) {
return $schemaManager->createSchema();
}
// whitelist assets we already know about in $toSchema, use the existing filter otherwise
$config->setSchemaAssetsFilter(static function ($asset) use ($previousFilter, $toSchema) : bool {
$assetName = $asset instanceof AbstractAsset ? $asset->getName() : $asset;
return $toSchema->hasTable($assetName) || $toSchema->hasSequence($assetName) || $previousFilter($asset);
});
try {
return $schemaManager->createSchema();
} finally {
// restore schema assets filter
$config->setSchemaAssetsFilter($previousFilter);
}
}
}
+1 -1
View File
@@ -37,7 +37,7 @@ class Version
/**
* Current Doctrine Version
*/
const VERSION = '2.7.0';
const VERSION = '2.7.1-DEV';
/**
* Compares a Doctrine version with the current one.
@@ -227,23 +227,6 @@ abstract class AbstractCollectionPersisterTest extends OrmTestCase
$this->assertFalse($persister->containsKey($collection, 0));
}
public function testInvokeRemoveElement()
{
$entity = new State("Foo");
$element = new State("Bar");
$persister = $this->createPersisterDefault();
$collection = $this->createCollection($entity);
$this->em->getUnitOfWork()->registerManaged($entity, ['id'=>1], ['id'=>1, 'name'=>'Foo']);
$this->collectionPersister->expects($this->once())
->method('removeElement')
->with($this->equalTo($collection), $this->equalTo($element))
->will($this->returnValue(false));
$this->assertFalse($persister->removeElement($collection, $element));
}
public function testInvokeGet()
{
$entity = new State("Foo");
@@ -28,6 +28,12 @@ class EntityManagerDecoratorTest extends TestCase
*/
private $wrapped;
/** @before */
public function ignoreDeprecationMessagesFromDoctrinePersistence() : void
{
$this->ignoreDeprecationMessage('The Doctrine\Common\Persistence\ObjectManagerDecorator class is deprecated since doctrine/persistence 1.3 and will be removed in 2.0. Use \Doctrine\Persistence\ObjectManagerDecorator instead.');
}
public function setUp()
{
$this->wrapped = $this->createMock(EntityManagerInterface::class);
File diff suppressed because it is too large Load Diff
@@ -14,9 +14,6 @@ class DDC2138Test extends OrmFunctionalTestCase
public function testForeignKeyOnSTIWithMultipleMapping()
{
$em = $this->_em;
if (! $em->getConnection()->getDatabasePlatform()->supportsForeignKeyConstraints()) {
$this->markTestSkipped('Platform does not support foreign keys.');
}
$schemaTool = new SchemaTool($em);
$classes = [
@@ -0,0 +1,92 @@
<?php
declare(strict_types=1);
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\OrmFunctionalTestCase;
/**
* @group GH7505
*/
final class GH7505Test extends OrmFunctionalTestCase
{
/**
* {@inheritDoc}
*/
protected function setUp() : void
{
parent::setUp();
$this->setUpEntitySchema([
GH7505AbstractResponse::class,
GH7505ArrayResponse::class,
GH7505TextResponse::class,
]);
}
public function testSimpleArrayTypeHydratedCorrectly() : void
{
$arrayResponse = new GH7505ArrayResponse();
$this->_em->persist($arrayResponse);
$textResponse = new GH7505TextResponse();
$this->_em->persist($textResponse);
$this->_em->flush();
$this->_em->clear();
$repository = $this->_em->getRepository(GH7505AbstractResponse::class);
/** @var GH7505ArrayResponse $arrayResponse */
$arrayResponse = $repository->find($arrayResponse->id);
self::assertSame([], $arrayResponse->value);
/** @var GH7505TextResponse $textResponse */
$textResponse = $repository->find($textResponse->id);
self::assertNull($textResponse->value);
}
}
/**
* @Entity()
* @Table(name="gh7505_responses")
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({
* "array" = GH7505ArrayResponse::class,
* "text" = GH7505TextResponse::class,
* })
*/
abstract class GH7505AbstractResponse
{
/**
* @Id @GeneratedValue
* @Column(type="integer")
*/
public $id;
}
/**
* @Entity()
*/
class GH7505ArrayResponse extends GH7505AbstractResponse
{
/**
* @Column(name="value_array", type="simple_array")
* @var array
*/
public $value = [];
}
/**
* @Entity()
*/
class GH7505TextResponse extends GH7505AbstractResponse
{
/**
* @Column(name="value_string", type="string")
* @var string|null
*/
public $value;
}
@@ -1,57 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Tests\OrmFunctionalTestCase;
/**
* @group GH7841
*/
class GH7841Test extends OrmFunctionalTestCase
{
public function testForeignKeysNotCompare() : void
{
if ($this->_em->getConnection()->getDatabasePlatform()->supportsForeignKeyConstraints()) {
$this->markTestSkipped('Test for platforms without foreign keys support');
}
$class = $this->_em->getClassMetadata(GH7841Child::class);
$this->_schemaTool->updateSchema([$class], true);
$diff = $this->_schemaTool->getUpdateSchemaSql([$class], true);
self::assertEmpty($diff);
$this->_schemaTool->dropSchema([$class]);
}
}
/**
* @Entity
*/
class GH7841Parent
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @OneToMany(targetEntity=GH7841Child::class, mappedBy="parent") */
public $children;
public function __construct()
{
$this->children = new ArrayCollection();
}
}
/**
* @Entity
*/
class GH7841Child
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @ManyToOne(targetEntity=GH7841Parent::class) */
public $parent;
}
@@ -0,0 +1,99 @@
<?php
declare(strict_types=1);
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Tests\OrmFunctionalTestCase;
use function array_values;
/**
* @group gh7864
*/
class GH7864Test extends OrmFunctionalTestCase
{
protected function setUp() : void
{
parent::setup();
$this->setUpEntitySchema(
[
GH7864User::class,
GH7864Tweet::class,
]
);
}
public function testExtraLazyRemoveElement()
{
$user = new GH7864User();
$user->name = 'test';
$tweet1 = new GH7864Tweet();
$tweet1->content = 'Hello World!';
$user->addTweet($tweet1);
$tweet2 = new GH7864Tweet();
$tweet2->content = 'Goodbye, and thanks for all the fish';
$user->addTweet($tweet2);
$this->_em->persist($user);
$this->_em->persist($tweet1);
$this->_em->persist($tweet2);
$this->_em->flush();
$this->_em->clear();
$user = $this->_em->find(GH7864User::class, $user->id);
$tweet = $this->_em->find(GH7864Tweet::class, $tweet1->id);
$user->tweets->removeElement($tweet);
$tweets = $user->tweets->map(static function (GH7864Tweet $tweet) {
return $tweet->content;
});
$this->assertEquals(['Goodbye, and thanks for all the fish'], array_values($tweets->toArray()));
}
}
/**
* @Entity
*/
class GH7864User
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @Column(type="string") */
public $name;
/** @OneToMany(targetEntity="GH7864Tweet", mappedBy="user", fetch="EXTRA_LAZY") */
public $tweets;
public function __construct()
{
$this->tweets = new ArrayCollection();
}
public function addTweet(GH7864Tweet $tweet)
{
$tweet->user = $this;
$this->tweets->add($tweet);
}
}
/**
* @Entity
*/
class GH7864Tweet
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @Column(type="string") */
public $content;
/** @ManyToOne(targetEntity="GH7864User", inversedBy="tweets") */
public $user;
}
@@ -0,0 +1,136 @@
<?php
declare(strict_types=1);
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\Tests\OrmFunctionalTestCase;
use function array_filter;
use function current;
use function method_exists;
use function sprintf;
use function strpos;
/** @group GH7875 */
final class GH7875Test extends OrmFunctionalTestCase
{
/** @after */
public function cleanUpSchema() : void
{
$connection = $this->_em->getConnection();
$connection->exec('DROP TABLE IF EXISTS gh7875_my_entity');
$connection->exec('DROP TABLE IF EXISTS gh7875_my_other_entity');
if ($connection->getDatabasePlatform() instanceof PostgreSqlPlatform) {
$connection->exec('DROP SEQUENCE IF EXISTS gh7875_my_entity_id_seq');
$connection->exec('DROP SEQUENCE IF EXISTS gh7875_my_other_entity_id_seq');
}
}
/**
* @param string[] $sqls
*
* @return string[]
*/
private function filterCreateTable(array $sqls, string $tableName) : array
{
return array_filter($sqls, static function (string $sql) use ($tableName) : bool {
return strpos($sql, sprintf('CREATE TABLE %s (', $tableName)) === 0;
});
}
public function testUpdateSchemaSql() : void
{
$classes = [$this->_em->getClassMetadata(GH7875MyEntity::class)];
$tool = new SchemaTool($this->_em);
$sqls = $this->filterCreateTable($tool->getUpdateSchemaSql($classes), 'gh7875_my_entity');
self::assertCount(1, $sqls);
$this->_em->getConnection()->exec(current($sqls));
$sqls = array_filter($tool->getUpdateSchemaSql($classes), static function (string $sql) : bool {
return strpos($sql, ' gh7875_my_entity ') !== false;
});
self::assertSame([], $sqls);
$classes[] = $this->_em->getClassMetadata(GH7875MyOtherEntity::class);
$sqls = $tool->getUpdateSchemaSql($classes);
self::assertCount(0, $this->filterCreateTable($sqls, 'gh7875_my_entity'));
self::assertCount(1, $this->filterCreateTable($sqls, 'gh7875_my_other_entity'));
}
/**
* @return array<array<string|callable|null>>
*/
public function provideUpdateSchemaSqlWithSchemaAssetFilter() : array
{
return [
['/^(?!my_enti)/', null],
[
null,
static function ($assetName) : bool {
return $assetName !== 'gh7875_my_entity';
},
],
];
}
/** @dataProvider provideUpdateSchemaSqlWithSchemaAssetFilter */
public function testUpdateSchemaSqlWithSchemaAssetFilter(?string $filterRegex, ?callable $filterCallback) : void
{
if ($filterRegex && ! method_exists(Configuration::class, 'setFilterSchemaAssetsExpression')) {
self::markTestSkipped(sprintf('Test require %s::setFilterSchemaAssetsExpression method', Configuration::class));
}
$classes = [$this->_em->getClassMetadata(GH7875MyEntity::class)];
$tool = new SchemaTool($this->_em);
$tool->createSchema($classes);
$config = $this->_em->getConnection()->getConfiguration();
if ($filterRegex) {
$config->setFilterSchemaAssetsExpression($filterRegex);
} else {
$config->setSchemaAssetsFilter($filterCallback);
}
$previousFilter = $config->getSchemaAssetsFilter();
$sqls = $tool->getUpdateSchemaSql($classes);
$sqls = array_filter($sqls, static function (string $sql) : bool {
return strpos($sql, ' gh7875_my_entity ') !== false;
});
self::assertCount(0, $sqls);
self::assertSame($previousFilter, $config->getSchemaAssetsFilter());
}
}
/**
* @Entity
* @Table(name="gh7875_my_entity")
*/
class GH7875MyEntity
{
/** @Id @Column(type="integer") @GeneratedValue(strategy="AUTO") */
public $id;
}
/**
* @Entity
* @Table(name="gh7875_my_other_entity")
*/
class GH7875MyOtherEntity
{
/** @Id @Column(type="integer") @GeneratedValue(strategy="AUTO") */
public $id;
}
@@ -328,6 +328,11 @@ class ValueObjectsTest extends OrmFunctionalTestCase
['DDCNestingEmbeddable1', 'DDCNestingEmbeddable4'],
];
}
public function testEmbeddableIsNotTransient()
{
$this->assertFalse($this->_em->getMetadataFactory()->isTransient(DDC93Address::class));
}
}
@@ -134,6 +134,8 @@ class LanguageRecognitionTest extends OrmTestCase
['SELECT \'foo\' AS foo\\\\bar FROM Doctrine\Tests\Models\CMS\CmsUser u'],
['SELECT \'foo\' AS foo: FROM Doctrine\Tests\Models\CMS\CmsUser u'],
['SELECT \'foo\' AS foo:bar FROM Doctrine\Tests\Models\CMS\CmsUser u'],
['0'],
];
}
@@ -134,6 +134,24 @@ class ParserTest extends OrmTestCase
];
}
/**
* PHP 7.4 would fail with Notice: Trying to access array offset on value of type null.
*
* @see https://github.com/doctrine/orm/pull/7934
*
* @group GH7934
*/
public function testNullLookahead() : void
{
$query = new Query($this->_getTestEntityManager());
$query->setDQL('SELECT CURRENT_TIMESTAMP()');
$parser = new Parser($query);
$this->expectException(QueryException::class);
$parser->match(Lexer::T_SELECT);
}
private function createParser($dql)
{
$query = new Query($this->_getTestEntityManager());
@@ -420,4 +420,13 @@ class QueryTest extends OrmTestCase
self::assertEmpty($query->getResult());
}
/** @group 7982 */
public function testNonExistentExecutor()
{
$this->expectException(QueryException::class);
$this->expectExceptionMessage('[Syntax Error] line 0, col -1: Error: Expected SELECT, UPDATE or DELETE, got end of string.');
$query = $this->_em->createQuery('0')->execute();
}
}
@@ -3,8 +3,8 @@
namespace Doctrine\Tests\ORM\Tools\Console;
use Doctrine\ORM\Tools\Console\ConsoleRunner;
use Doctrine\ORM\Version;
use Doctrine\Tests\DoctrineTestCase;
use PackageVersions\Versions;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\HelperSet;
@@ -21,7 +21,7 @@ final class ConsoleRunnerTest extends DoctrineTestCase
$app = ConsoleRunner::createApplication($helperSet);
self::assertSame($helperSet, $app->getHelperSet());
self::assertEquals(Version::VERSION, $app->getVersion());
self::assertSame(Versions::getVersion('doctrine/orm'), $app->getVersion());
self::assertTrue($app->has('dbal:import'));
self::assertTrue($app->has('dbal:reserved-words'));
@@ -13,6 +13,7 @@ use Doctrine\Tests\Models\DDC2372\DDC2372Admin;
use Doctrine\Tests\Models\DDC2372\DDC2372User;
use Doctrine\Tests\OrmTestCase;
use Doctrine\Tests\VerifyDeprecations;
use ReflectionClass;
class EntityGeneratorTest extends OrmTestCase
{
@@ -327,6 +328,25 @@ class EntityGeneratorTest extends OrmTestCase
$this->assertEquals($isbnMetadata->name, $reflParameters[0]->getClass()->name);
}
public function testBooleanDefaultValue()
{
$metadata = $this->generateBookEntityFixture(['isbn' => $this->generateIsbnEmbeddableFixture()]);
$metadata->mapField(['fieldName' => 'foo', 'type' => 'boolean', 'options' => ['default' => '1']]);
$testEmbeddableMetadata = $this->generateTestEmbeddableFixture();
$this->mapEmbedded('testEmbedded', $metadata, $testEmbeddableMetadata);
$this->_generator->writeEntityClass($metadata, $this->_tmpDir);
$this->assertFileExists($this->_tmpDir . '/' . $this->_namespace . '/EntityGeneratorBook.php~');
$book = $this->newInstance($metadata);
$reflClass = new ReflectionClass($metadata->name);
$this->assertTrue($book->getfoo());
}
public function testEntityUpdatingWorks()
{
$metadata = $this->generateBookEntityFixture(['isbn' => $this->generateIsbnEmbeddableFixture()]);
@@ -9,7 +9,6 @@ use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
use Doctrine\ORM\Mapping\Driver\XmlDriver;
use Doctrine\ORM\Mapping\Driver\YamlDriver;
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\Version;
use Doctrine\Tests\OrmTestCase;
use Doctrine\Tests\VerifyDeprecations;
@@ -22,10 +21,6 @@ class SetupTest extends OrmTestCase
public function setUp()
{
if (strpos(Version::VERSION, "DEV") === false) {
$this->markTestSkipped("Test only runs in a dev-installation from Github");
}
$this->originalAutoloaderCount = count(spl_autoload_functions());
$this->originalIncludePath = get_include_path();
}
+16 -1
View File
@@ -1,10 +1,12 @@
<?php
declare(strict_types=1);
namespace Doctrine\Tests;
use function set_error_handler;
use const E_USER_DEPRECATED;
use function in_array;
use function set_error_handler;
trait VerifyDeprecations
{
@@ -14,6 +16,9 @@ trait VerifyDeprecations
/** @var string[] */
private $actualDeprecations = [];
/** @var string[] */
private $ignoredDeprecations = [];
/** @var callable|null */
private $originalHandler;
@@ -22,9 +27,14 @@ trait VerifyDeprecations
{
$this->actualDeprecations = [];
$this->expectedDeprecations = [];
$this->ignoredDeprecations = [];
$this->originalHandler = set_error_handler(
function (int $errorNumber, string $errorMessage) : void {
if (in_array($errorMessage, $this->ignoredDeprecations, true)) {
return;
}
$this->actualDeprecations[] = $errorMessage;
},
E_USER_DEPRECATED
@@ -52,6 +62,11 @@ trait VerifyDeprecations
);
}
protected function ignoreDeprecationMessage(string $message) : void
{
$this->ignoredDeprecations[] = $message;
}
protected function expectDeprecationMessage(string $message) : void
{
$this->expectedDeprecations[] = $message;