summaryrefslogtreecommitdiff
path: root/vendor/doctrine/deprecations
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/doctrine/deprecations')
-rw-r--r--vendor/doctrine/deprecations/LICENSE19
-rw-r--r--vendor/doctrine/deprecations/README.md157
-rw-r--r--vendor/doctrine/deprecations/composer.json38
-rw-r--r--vendor/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php313
-rw-r--r--vendor/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php66
5 files changed, 593 insertions, 0 deletions
diff --git a/vendor/doctrine/deprecations/LICENSE b/vendor/doctrine/deprecations/LICENSE
new file mode 100644
index 0000000..156905c
--- /dev/null
+++ b/vendor/doctrine/deprecations/LICENSE
@@ -0,0 +1,19 @@
1Copyright (c) 2020-2021 Doctrine Project
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of
4this software and associated documentation files (the "Software"), to deal in
5the Software without restriction, including without limitation the rights to
6use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7of the Software, and to permit persons to whom the Software is furnished to do
8so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in all
11copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19SOFTWARE.
diff --git a/vendor/doctrine/deprecations/README.md b/vendor/doctrine/deprecations/README.md
new file mode 100644
index 0000000..93caf83
--- /dev/null
+++ b/vendor/doctrine/deprecations/README.md
@@ -0,0 +1,157 @@
1# Doctrine Deprecations
2
3A small (side-effect free by default) layer on top of
4`trigger_error(E_USER_DEPRECATED)` or PSR-3 logging.
5
6- no side-effects by default, making it a perfect fit for libraries that don't know how the error handler works they operate under
7- options to avoid having to rely on error handlers global state by using PSR-3 logging
8- deduplicate deprecation messages to avoid excessive triggering and reduce overhead
9
10We recommend to collect Deprecations using a PSR logger instead of relying on
11the global error handler.
12
13## Usage from consumer perspective:
14
15Enable Doctrine deprecations to be sent to a PSR3 logger:
16
17```php
18\Doctrine\Deprecations\Deprecation::enableWithPsrLogger($logger);
19```
20
21Enable Doctrine deprecations to be sent as `@trigger_error($message, E_USER_DEPRECATED)`
22messages by setting the `DOCTRINE_DEPRECATIONS` environment variable to `trigger`.
23Alternatively, call:
24
25```php
26\Doctrine\Deprecations\Deprecation::enableWithTriggerError();
27```
28
29If you only want to enable deprecation tracking, without logging or calling `trigger_error`
30then set the `DOCTRINE_DEPRECATIONS` environment variable to `track`.
31Alternatively, call:
32
33```php
34\Doctrine\Deprecations\Deprecation::enableTrackingDeprecations();
35```
36
37Tracking is enabled with all three modes and provides access to all triggered
38deprecations and their individual count:
39
40```php
41$deprecations = \Doctrine\Deprecations\Deprecation::getTriggeredDeprecations();
42
43foreach ($deprecations as $identifier => $count) {
44 echo $identifier . " was triggered " . $count . " times\n";
45}
46```
47
48### Suppressing Specific Deprecations
49
50Disable triggering about specific deprecations:
51
52```php
53\Doctrine\Deprecations\Deprecation::ignoreDeprecations("https://link/to/deprecations-description-identifier");
54```
55
56Disable all deprecations from a package
57
58```php
59\Doctrine\Deprecations\Deprecation::ignorePackage("doctrine/orm");
60```
61
62### Other Operations
63
64When used within PHPUnit or other tools that could collect multiple instances of the same deprecations
65the deduplication can be disabled:
66
67```php
68\Doctrine\Deprecations\Deprecation::withoutDeduplication();
69```
70
71Disable deprecation tracking again:
72
73```php
74\Doctrine\Deprecations\Deprecation::disable();
75```
76
77## Usage from a library/producer perspective:
78
79When you want to unconditionally trigger a deprecation even when called
80from the library itself then the `trigger` method is the way to go:
81
82```php
83\Doctrine\Deprecations\Deprecation::trigger(
84 "doctrine/orm",
85 "https://link/to/deprecations-description",
86 "message"
87);
88```
89
90If variable arguments are provided at the end, they are used with `sprintf` on
91the message.
92
93```php
94\Doctrine\Deprecations\Deprecation::trigger(
95 "doctrine/orm",
96 "https://github.com/doctrine/orm/issue/1234",
97 "message %s %d",
98 "foo",
99 1234
100);
101```
102
103When you want to trigger a deprecation only when it is called by a function
104outside of the current package, but not trigger when the package itself is the cause,
105then use:
106
107```php
108\Doctrine\Deprecations\Deprecation::triggerIfCalledFromOutside(
109 "doctrine/orm",
110 "https://link/to/deprecations-description",
111 "message"
112);
113```
114
115Based on the issue link each deprecation message is only triggered once per
116request.
117
118A limited stacktrace is included in the deprecation message to find the
119offending location.
120
121Note: A producer/library should never call `Deprecation::enableWith` methods
122and leave the decision how to handle deprecations to application and
123frameworks.
124
125## Usage in PHPUnit tests
126
127There is a `VerifyDeprecations` trait that you can use to make assertions on
128the occurrence of deprecations within a test.
129
130```php
131use Doctrine\Deprecations\PHPUnit\VerifyDeprecations;
132
133class MyTest extends TestCase
134{
135 use VerifyDeprecations;
136
137 public function testSomethingDeprecation()
138 {
139 $this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/issue/1234');
140
141 triggerTheCodeWithDeprecation();
142 }
143
144 public function testSomethingDeprecationFixed()
145 {
146 $this->expectNoDeprecationWithIdentifier('https://github.com/doctrine/orm/issue/1234');
147
148 triggerTheCodeWithoutDeprecation();
149 }
150}
151```
152
153## What is a deprecation identifier?
154
155An identifier for deprecations is just a link to any resource, most often a
156Github Issue or Pull Request explaining the deprecation and potentially its
157alternative.
diff --git a/vendor/doctrine/deprecations/composer.json b/vendor/doctrine/deprecations/composer.json
new file mode 100644
index 0000000..f8319f9
--- /dev/null
+++ b/vendor/doctrine/deprecations/composer.json
@@ -0,0 +1,38 @@
1{
2 "name": "doctrine/deprecations",
3 "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
4 "license": "MIT",
5 "type": "library",
6 "homepage": "https://www.doctrine-project.org/",
7 "require": {
8 "php": "^7.1 || ^8.0"
9 },
10 "require-dev": {
11 "doctrine/coding-standard": "^9",
12 "phpstan/phpstan": "1.4.10 || 1.10.15",
13 "phpstan/phpstan-phpunit": "^1.0",
14 "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
15 "psalm/plugin-phpunit": "0.18.4",
16 "psr/log": "^1 || ^2 || ^3",
17 "vimeo/psalm": "4.30.0 || 5.12.0"
18 },
19 "suggest": {
20 "psr/log": "Allows logging deprecations via PSR-3 logger implementation"
21 },
22 "autoload": {
23 "psr-4": {
24 "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations"
25 }
26 },
27 "autoload-dev": {
28 "psr-4": {
29 "DeprecationTests\\": "test_fixtures/src",
30 "Doctrine\\Foo\\": "test_fixtures/vendor/doctrine/foo"
31 }
32 },
33 "config": {
34 "allow-plugins": {
35 "dealerdirect/phpcodesniffer-composer-installer": true
36 }
37 }
38}
diff --git a/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php b/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php
new file mode 100644
index 0000000..bad5070
--- /dev/null
+++ b/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/Deprecation.php
@@ -0,0 +1,313 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Deprecations;
6
7use Psr\Log\LoggerInterface;
8
9use function array_key_exists;
10use function array_reduce;
11use function assert;
12use function debug_backtrace;
13use function sprintf;
14use function str_replace;
15use function strpos;
16use function strrpos;
17use function substr;
18use function trigger_error;
19
20use const DEBUG_BACKTRACE_IGNORE_ARGS;
21use const DIRECTORY_SEPARATOR;
22use const E_USER_DEPRECATED;
23
24/**
25 * Manages Deprecation logging in different ways.
26 *
27 * By default triggered exceptions are not logged.
28 *
29 * To enable different deprecation logging mechanisms you can call the
30 * following methods:
31 *
32 * - Minimal collection of deprecations via getTriggeredDeprecations()
33 * \Doctrine\Deprecations\Deprecation::enableTrackingDeprecations();
34 *
35 * - Uses @trigger_error with E_USER_DEPRECATED
36 * \Doctrine\Deprecations\Deprecation::enableWithTriggerError();
37 *
38 * - Sends deprecation messages via a PSR-3 logger
39 * \Doctrine\Deprecations\Deprecation::enableWithPsrLogger($logger);
40 *
41 * Packages that trigger deprecations should use the `trigger()` or
42 * `triggerIfCalledFromOutside()` methods.
43 */
44class Deprecation
45{
46 private const TYPE_NONE = 0;
47 private const TYPE_TRACK_DEPRECATIONS = 1;
48 private const TYPE_TRIGGER_ERROR = 2;
49 private const TYPE_PSR_LOGGER = 4;
50
51 /** @var int-mask-of<self::TYPE_*>|null */
52 private static $type;
53
54 /** @var LoggerInterface|null */
55 private static $logger;
56
57 /** @var array<string,bool> */
58 private static $ignoredPackages = [];
59
60 /** @var array<string,int> */
61 private static $triggeredDeprecations = [];
62
63 /** @var array<string,bool> */
64 private static $ignoredLinks = [];
65
66 /** @var bool */
67 private static $deduplication = true;
68
69 /**
70 * Trigger a deprecation for the given package and identfier.
71 *
72 * The link should point to a Github issue or Wiki entry detailing the
73 * deprecation. It is additionally used to de-duplicate the trigger of the
74 * same deprecation during a request.
75 *
76 * @param float|int|string $args
77 */
78 public static function trigger(string $package, string $link, string $message, ...$args): void
79 {
80 $type = self::$type ?? self::getTypeFromEnv();
81
82 if ($type === self::TYPE_NONE) {
83 return;
84 }
85
86 if (isset(self::$ignoredLinks[$link])) {
87 return;
88 }
89
90 if (array_key_exists($link, self::$triggeredDeprecations)) {
91 self::$triggeredDeprecations[$link]++;
92 } else {
93 self::$triggeredDeprecations[$link] = 1;
94 }
95
96 if (self::$deduplication === true && self::$triggeredDeprecations[$link] > 1) {
97 return;
98 }
99
100 if (isset(self::$ignoredPackages[$package])) {
101 return;
102 }
103
104 $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
105
106 $message = sprintf($message, ...$args);
107
108 self::delegateTriggerToBackend($message, $backtrace, $link, $package);
109 }
110
111 /**
112 * Trigger a deprecation for the given package and identifier when called from outside.
113 *
114 * "Outside" means we assume that $package is currently installed as a
115 * dependency and the caller is not a file in that package. When $package
116 * is installed as a root package then deprecations triggered from the
117 * tests folder are also considered "outside".
118 *
119 * This deprecation method assumes that you are using Composer to install
120 * the dependency and are using the default /vendor/ folder and not a
121 * Composer plugin to change the install location. The assumption is also
122 * that $package is the exact composer packge name.
123 *
124 * Compared to {@link trigger()} this method causes some overhead when
125 * deprecation tracking is enabled even during deduplication, because it
126 * needs to call {@link debug_backtrace()}
127 *
128 * @param float|int|string $args
129 */
130 public static function triggerIfCalledFromOutside(string $package, string $link, string $message, ...$args): void
131 {
132 $type = self::$type ?? self::getTypeFromEnv();
133
134 if ($type === self::TYPE_NONE) {
135 return;
136 }
137
138 $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
139
140 // first check that the caller is not from a tests folder, in which case we always let deprecations pass
141 if (isset($backtrace[1]['file'], $backtrace[0]['file']) && strpos($backtrace[1]['file'], DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR) === false) {
142 $path = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $package) . DIRECTORY_SEPARATOR;
143
144 if (strpos($backtrace[0]['file'], $path) === false) {
145 return;
146 }
147
148 if (strpos($backtrace[1]['file'], $path) !== false) {
149 return;
150 }
151 }
152
153 if (isset(self::$ignoredLinks[$link])) {
154 return;
155 }
156
157 if (array_key_exists($link, self::$triggeredDeprecations)) {
158 self::$triggeredDeprecations[$link]++;
159 } else {
160 self::$triggeredDeprecations[$link] = 1;
161 }
162
163 if (self::$deduplication === true && self::$triggeredDeprecations[$link] > 1) {
164 return;
165 }
166
167 if (isset(self::$ignoredPackages[$package])) {
168 return;
169 }
170
171 $message = sprintf($message, ...$args);
172
173 self::delegateTriggerToBackend($message, $backtrace, $link, $package);
174 }
175
176 /**
177 * @param list<array{function: string, line?: int, file?: string, class?: class-string, type?: string, args?: mixed[], object?: object}> $backtrace
178 */
179 private static function delegateTriggerToBackend(string $message, array $backtrace, string $link, string $package): void
180 {
181 $type = self::$type ?? self::getTypeFromEnv();
182
183 if (($type & self::TYPE_PSR_LOGGER) > 0) {
184 $context = [
185 'file' => $backtrace[0]['file'] ?? null,
186 'line' => $backtrace[0]['line'] ?? null,
187 'package' => $package,
188 'link' => $link,
189 ];
190
191 assert(self::$logger !== null);
192
193 self::$logger->notice($message, $context);
194 }
195
196 if (! (($type & self::TYPE_TRIGGER_ERROR) > 0)) {
197 return;
198 }
199
200 $message .= sprintf(
201 ' (%s:%d called by %s:%d, %s, package %s)',
202 self::basename($backtrace[0]['file'] ?? 'native code'),
203 $backtrace[0]['line'] ?? 0,
204 self::basename($backtrace[1]['file'] ?? 'native code'),
205 $backtrace[1]['line'] ?? 0,
206 $link,
207 $package
208 );
209
210 @trigger_error($message, E_USER_DEPRECATED);
211 }
212
213 /**
214 * A non-local-aware version of PHPs basename function.
215 */
216 private static function basename(string $filename): string
217 {
218 $pos = strrpos($filename, DIRECTORY_SEPARATOR);
219
220 if ($pos === false) {
221 return $filename;
222 }
223
224 return substr($filename, $pos + 1);
225 }
226
227 public static function enableTrackingDeprecations(): void
228 {
229 self::$type = self::$type ?? 0;
230 self::$type |= self::TYPE_TRACK_DEPRECATIONS;
231 }
232
233 public static function enableWithTriggerError(): void
234 {
235 self::$type = self::$type ?? 0;
236 self::$type |= self::TYPE_TRIGGER_ERROR;
237 }
238
239 public static function enableWithPsrLogger(LoggerInterface $logger): void
240 {
241 self::$type = self::$type ?? 0;
242 self::$type |= self::TYPE_PSR_LOGGER;
243 self::$logger = $logger;
244 }
245
246 public static function withoutDeduplication(): void
247 {
248 self::$deduplication = false;
249 }
250
251 public static function disable(): void
252 {
253 self::$type = self::TYPE_NONE;
254 self::$logger = null;
255 self::$deduplication = true;
256 self::$ignoredLinks = [];
257
258 foreach (self::$triggeredDeprecations as $link => $count) {
259 self::$triggeredDeprecations[$link] = 0;
260 }
261 }
262
263 public static function ignorePackage(string $packageName): void
264 {
265 self::$ignoredPackages[$packageName] = true;
266 }
267
268 public static function ignoreDeprecations(string ...$links): void
269 {
270 foreach ($links as $link) {
271 self::$ignoredLinks[$link] = true;
272 }
273 }
274
275 public static function getUniqueTriggeredDeprecationsCount(): int
276 {
277 return array_reduce(self::$triggeredDeprecations, static function (int $carry, int $count) {
278 return $carry + $count;
279 }, 0);
280 }
281
282 /**
283 * Returns each triggered deprecation link identifier and the amount of occurrences.
284 *
285 * @return array<string,int>
286 */
287 public static function getTriggeredDeprecations(): array
288 {
289 return self::$triggeredDeprecations;
290 }
291
292 /**
293 * @return int-mask-of<self::TYPE_*>
294 */
295 private static function getTypeFromEnv(): int
296 {
297 switch ($_SERVER['DOCTRINE_DEPRECATIONS'] ?? $_ENV['DOCTRINE_DEPRECATIONS'] ?? null) {
298 case 'trigger':
299 self::$type = self::TYPE_TRIGGER_ERROR;
300 break;
301
302 case 'track':
303 self::$type = self::TYPE_TRACK_DEPRECATIONS;
304 break;
305
306 default:
307 self::$type = self::TYPE_NONE;
308 break;
309 }
310
311 return self::$type;
312 }
313}
diff --git a/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php b/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php
new file mode 100644
index 0000000..4c3366a
--- /dev/null
+++ b/vendor/doctrine/deprecations/lib/Doctrine/Deprecations/PHPUnit/VerifyDeprecations.php
@@ -0,0 +1,66 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Deprecations\PHPUnit;
6
7use Doctrine\Deprecations\Deprecation;
8
9use function sprintf;
10
11trait VerifyDeprecations
12{
13 /** @var array<string,int> */
14 private $doctrineDeprecationsExpectations = [];
15
16 /** @var array<string,int> */
17 private $doctrineNoDeprecationsExpectations = [];
18
19 public function expectDeprecationWithIdentifier(string $identifier): void
20 {
21 $this->doctrineDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
22 }
23
24 public function expectNoDeprecationWithIdentifier(string $identifier): void
25 {
26 $this->doctrineNoDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
27 }
28
29 /**
30 * @before
31 */
32 public function enableDeprecationTracking(): void
33 {
34 Deprecation::enableTrackingDeprecations();
35 }
36
37 /**
38 * @after
39 */
40 public function verifyDeprecationsAreTriggered(): void
41 {
42 foreach ($this->doctrineDeprecationsExpectations as $identifier => $expectation) {
43 $actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
44
45 $this->assertTrue(
46 $actualCount > $expectation,
47 sprintf(
48 "Expected deprecation with identifier '%s' was not triggered by code executed in test.",
49 $identifier
50 )
51 );
52 }
53
54 foreach ($this->doctrineNoDeprecationsExpectations as $identifier => $expectation) {
55 $actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
56
57 $this->assertTrue(
58 $actualCount === $expectation,
59 sprintf(
60 "Expected deprecation with identifier '%s' was triggered by code executed in test, but expected not to.",
61 $identifier
62 )
63 );
64 }
65 }
66}