mirror of
https://gitlab.com/signalytic/client-external/streamline/streamline-emr.git
synced 2026-09-13 03:31:31 +00:00
updated streamline-setup v2
This commit is contained in:
@@ -139,8 +139,6 @@ Instantiating the class will give you an object with available methods
|
||||
- `unit`: Mobile data unit. Can either be `MB` or `GB`. `REQUIRED`
|
||||
- `validity`: How long the mobile data is valid for. Must be one of `Day`, `Week` and `Month`. `REQUIRED`
|
||||
- `metadata`: Additional data to associate with the tranasction. `REQUIRED`
|
||||
|
||||
- `isPromoBundle`: This is an optional field that can be either `true` or `false`.
|
||||
|
||||
- **$options:** optional associative array with the following keys:
|
||||
|
||||
|
||||
@@ -21,7 +21,11 @@
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"AfricasTalking\\SDK\\": "src/",
|
||||
"AfricasTalking\\SDK\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"AfricasTalking\\SDK\\Tests\\": "tests"
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -12,13 +12,16 @@ class AfricasTalking
|
||||
protected $apiKey;
|
||||
|
||||
protected $client;
|
||||
protected $contentClient;
|
||||
protected $voiceClient;
|
||||
protected $tokenClient;
|
||||
protected $contentClient;
|
||||
protected $mobileDataClient;
|
||||
|
||||
protected $baseDomain;
|
||||
|
||||
public $baseUrl;
|
||||
protected $voiceUrl;
|
||||
protected $checkoutTokenUrl;
|
||||
protected $contentUrl;
|
||||
protected $mobileDataUrl;
|
||||
|
||||
|
||||
@@ -68,6 +68,16 @@ class Content extends Service
|
||||
'keyword' => $options['keyword']
|
||||
];
|
||||
|
||||
/**
|
||||
* checkoutToken Key was removed in commit:339f7057d8ff640ffa9802b4d3a812848b1072a9.
|
||||
* To prevent breaking applications in production, we conditionally add it to
|
||||
* the request otherwise previous behaviour persists.
|
||||
**/
|
||||
|
||||
if(array_key_exists('checkoutToken',$options)){
|
||||
$data['checkoutToken'] = $options['checkoutToken'];
|
||||
}
|
||||
|
||||
$response = $this->client->post('subscription/create', ['form_params' => $data ] );
|
||||
|
||||
return $this->success($response);
|
||||
|
||||
@@ -63,10 +63,6 @@ class MobileData extends Service
|
||||
'recipients' => $recipients,
|
||||
];
|
||||
|
||||
if (isset($parameters['isPromoBundles'])) {
|
||||
$requestData['isPromoBundle'] = $parameters['isPromoBundles'];
|
||||
}
|
||||
|
||||
$requestOptions = [
|
||||
'json' => $requestData,
|
||||
];
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ namespace AfricasTalking\SDK\Tests;
|
||||
use AfricasTalking\SDK\AfricasTalking;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
class AfricasTalkingTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ namespace AfricasTalking\SDK\Tests;
|
||||
use AfricasTalking\SDK\AfricasTalking;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
class AirtimeTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function setup(): void
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ namespace AfricasTalking\SDK\Tests;
|
||||
use AfricasTalking\SDK\AfricasTalking;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
class ApplicationTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ namespace AfricasTalking\SDK\Tests;
|
||||
use AfricasTalking\SDK\AfricasTalking;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
class ContentTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace AfricasTalking\SDK\Tests;
|
||||
use AfricasTalking\SDK\AfricasTalking;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
class SMSTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
@@ -108,7 +109,9 @@ class SMSTest extends \PHPUnit\Framework\TestCase
|
||||
]);
|
||||
|
||||
$this->assertArrayHasKey('status',$response);
|
||||
$this->assertArrayHasKey('data',$response);
|
||||
$this->assertEquals('success',$response['status']);
|
||||
$this->assertEquals('Success',$response['data']->status);
|
||||
}
|
||||
|
||||
public function testDeleteSubscription()
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ namespace AfricasTalking\SDK\Tests;
|
||||
use AfricasTalking\SDK\AfricasTalking;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
class TokenTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ namespace AfricasTalking\SDK\Tests;
|
||||
use AfricasTalking\SDK\AfricasTalking;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
class VoiceTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
|
||||
+1
-1
@@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit379a36e429894b61b55afc3b84fa116a::getLoader();
|
||||
return ComposerAutoloaderInit69a41de4ce3c76c7865a7de0eec12ccc::getLoader();
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [2.0.0-beta3]
|
||||
### Changed
|
||||
- Remove the deprecated class 'Barryvdh\DomPDF\Facade' Facade in favor of Barryvdh\DomPDF\Facade\Pdf
|
||||
- Set default Facade to Pdf instead of PDF
|
||||
|
||||
## [2.0.0-beta2]
|
||||
|
||||
### Added
|
||||
- Upgraded to use dompdf/dompdf 2.x
|
||||
- `setOption` to change only the specified option(s), instead of replace all options.
|
||||
- Magic methods to allow calls to Dompdf methods easier. (#892)
|
||||
- `default_paper_orientation` option has been added to the defaults.
|
||||
- Add option to set public path (#890)
|
||||
|
||||
### Changed
|
||||
- HTML5 parser option is deprecated, because this is always on.
|
||||
- `orientation` option was never used. Removed in favor of `options.default_paper_orientation`
|
||||
|
||||
### Deprecated
|
||||
- `setOptions` is now deprecated. Use `setOption` instead.
|
||||
- Config `dompdf.defines` has been renamed to `dompdf.options`
|
||||
|
||||
|
||||
## Dompdf 2.0.0, highlights since 1.2.x
|
||||
> https://github.com/dompdf/dompdf/releases/tag/v2.0.0
|
||||
> - Addresses multiple security vulnerabilities (see link)
|
||||
> - Modifies callback and page_script/page_text handling (breaking change, see link)
|
||||
> - Switches the HTML5 parser to Masterminds/HTML5
|
||||
> - Improves CSS property parsing and representation
|
||||
> - Improves border, outline, and background rendering for inline elements
|
||||
> - Switches installed fonts and font metrics cache file format to JSON
|
||||
> - Adds support for the inset CSS shorthand property and the legacy break-word keyword for word-break
|
||||
> - Adds "end_document" callback event
|
||||
+7
-5
@@ -1,11 +1,13 @@
|
||||
Copyright (c) 2015-present Fabien Potencier
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 barryvdh
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
@@ -15,5 +17,5 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "barryvdh/laravel-dompdf",
|
||||
"description": "A DOMPDF Wrapper for Laravel",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"dompdf",
|
||||
"pdf"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Barry vd. Heuvel",
|
||||
"email": "barryvdh@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0",
|
||||
"dompdf/dompdf": "^2.0.7",
|
||||
"illuminate/support": "^6|^7|^8|^9|^10|^11"
|
||||
},
|
||||
"require-dev": {
|
||||
"orchestra/testbench": "^4|^5|^6|^7|^8|^9",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"phpro/grumphp": "^1 || ^2.5",
|
||||
"larastan/larastan": "^1.0|^2.7.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Barryvdh\\DomPDF\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Barryvdh\\DomPDF\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Barryvdh\\DomPDF\\ServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
"Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf",
|
||||
"PDF": "Barryvdh\\DomPDF\\Facade\\Pdf"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": "phpunit",
|
||||
"check-style": "phpcs -p --standard=psr12 src/",
|
||||
"fix-style": "phpcbf -p --standard=psr12 src/",
|
||||
"phpstan": "phpstan analyze --memory-limit=-1"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"phpro/grumphp": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Set some default values. It is possible to add all defines that can be set
|
||||
| in dompdf_config.inc.php. You can also override the entire config file.
|
||||
|
|
||||
*/
|
||||
'show_warnings' => false, // Throw an Exception on warnings from dompdf
|
||||
|
||||
'public_path' => null, // Override the public path if needed
|
||||
|
||||
/*
|
||||
* Dejavu Sans font is missing glyphs for converted entities, turn it off if you need to show € and £.
|
||||
*/
|
||||
'convert_entities' => true,
|
||||
|
||||
'options' => array(
|
||||
/**
|
||||
* The location of the DOMPDF font directory
|
||||
*
|
||||
* The location of the directory where DOMPDF will store fonts and font metrics
|
||||
* Note: This directory must exist and be writable by the webserver process.
|
||||
* *Please note the trailing slash.*
|
||||
*
|
||||
* Notes regarding fonts:
|
||||
* Additional .afm font metrics can be added by executing load_font.php from command line.
|
||||
*
|
||||
* Only the original "Base 14 fonts" are present on all pdf viewers. Additional fonts must
|
||||
* be embedded in the pdf file or the PDF may not display correctly. This can significantly
|
||||
* increase file size unless font subsetting is enabled. Before embedding a font please
|
||||
* review your rights under the font license.
|
||||
*
|
||||
* Any font specification in the source HTML is translated to the closest font available
|
||||
* in the font directory.
|
||||
*
|
||||
* The pdf standard "Base 14 fonts" are:
|
||||
* Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique,
|
||||
* Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique,
|
||||
* Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic,
|
||||
* Symbol, ZapfDingbats.
|
||||
*/
|
||||
"font_dir" => storage_path('fonts'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
|
||||
|
||||
/**
|
||||
* The location of the DOMPDF font cache directory
|
||||
*
|
||||
* This directory contains the cached font metrics for the fonts used by DOMPDF.
|
||||
* This directory can be the same as DOMPDF_FONT_DIR
|
||||
*
|
||||
* Note: This directory must exist and be writable by the webserver process.
|
||||
*/
|
||||
"font_cache" => storage_path('fonts'),
|
||||
|
||||
/**
|
||||
* The location of a temporary directory.
|
||||
*
|
||||
* The directory specified must be writeable by the webserver process.
|
||||
* The temporary directory is required to download remote images and when
|
||||
* using the PDFLib back end.
|
||||
*/
|
||||
"temp_dir" => sys_get_temp_dir(),
|
||||
|
||||
/**
|
||||
* ==== IMPORTANT ====
|
||||
*
|
||||
* dompdf's "chroot": Prevents dompdf from accessing system files or other
|
||||
* files on the webserver. All local files opened by dompdf must be in a
|
||||
* subdirectory of this directory. DO NOT set it to '/' since this could
|
||||
* allow an attacker to use dompdf to read any files on the server. This
|
||||
* should be an absolute path.
|
||||
* This is only checked on command line call by dompdf.php, but not by
|
||||
* direct class use like:
|
||||
* $dompdf = new DOMPDF(); $dompdf->load_html($htmldata); $dompdf->render(); $pdfdata = $dompdf->output();
|
||||
*/
|
||||
"chroot" => realpath(base_path()),
|
||||
|
||||
/**
|
||||
* Protocol whitelist
|
||||
*
|
||||
* Protocols and PHP wrappers allowed in URIs, and the validation rules
|
||||
* that determine if a resouce may be loaded. Full support is not guaranteed
|
||||
* for the protocols/wrappers specified
|
||||
* by this array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
'allowed_protocols' => [
|
||||
"file://" => ["rules" => []],
|
||||
"http://" => ["rules" => []],
|
||||
"https://" => ["rules" => []]
|
||||
],
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
'log_output_file' => null,
|
||||
|
||||
/**
|
||||
* Whether to enable font subsetting or not.
|
||||
*/
|
||||
"enable_font_subsetting" => false,
|
||||
|
||||
/**
|
||||
* The PDF rendering backend to use
|
||||
*
|
||||
* Valid settings are 'PDFLib', 'CPDF' (the bundled R&OS PDF class), 'GD' and
|
||||
* 'auto'. 'auto' will look for PDFLib and use it if found, or if not it will
|
||||
* fall back on CPDF. 'GD' renders PDFs to graphic files. {@link
|
||||
* Canvas_Factory} ultimately determines which rendering class to instantiate
|
||||
* based on this setting.
|
||||
*
|
||||
* Both PDFLib & CPDF rendering backends provide sufficient rendering
|
||||
* capabilities for dompdf, however additional features (e.g. object,
|
||||
* image and font support, etc.) differ between backends. Please see
|
||||
* {@link PDFLib_Adapter} for more information on the PDFLib backend
|
||||
* and {@link CPDF_Adapter} and lib/class.pdf.php for more information
|
||||
* on CPDF. Also see the documentation for each backend at the links
|
||||
* below.
|
||||
*
|
||||
* The GD rendering backend is a little different than PDFLib and
|
||||
* CPDF. Several features of CPDF and PDFLib are not supported or do
|
||||
* not make any sense when creating image files. For example,
|
||||
* multiple pages are not supported, nor are PDF 'objects'. Have a
|
||||
* look at {@link GD_Adapter} for more information. GD support is
|
||||
* experimental, so use it at your own risk.
|
||||
*
|
||||
* @link http://www.pdflib.com
|
||||
* @link http://www.ros.co.nz/pdf
|
||||
* @link http://www.php.net/image
|
||||
*/
|
||||
"pdf_backend" => "CPDF",
|
||||
|
||||
/**
|
||||
* PDFlib license key
|
||||
*
|
||||
* If you are using a licensed, commercial version of PDFlib, specify
|
||||
* your license key here. If you are using PDFlib-Lite or are evaluating
|
||||
* the commercial version of PDFlib, comment out this setting.
|
||||
*
|
||||
* @link http://www.pdflib.com
|
||||
*
|
||||
* If pdflib present in web server and auto or selected explicitely above,
|
||||
* a real license code must exist!
|
||||
*/
|
||||
//"DOMPDF_PDFLIB_LICENSE" => "your license key here",
|
||||
|
||||
/**
|
||||
* html target media view which should be rendered into pdf.
|
||||
* List of types and parsing rules for future extensions:
|
||||
* http://www.w3.org/TR/REC-html40/types.html
|
||||
* screen, tty, tv, projection, handheld, print, braille, aural, all
|
||||
* Note: aural is deprecated in CSS 2.1 because it is replaced by speech in CSS 3.
|
||||
* Note, even though the generated pdf file is intended for print output,
|
||||
* the desired content might be different (e.g. screen or projection view of html file).
|
||||
* Therefore allow specification of content here.
|
||||
*/
|
||||
"default_media_type" => "screen",
|
||||
|
||||
/**
|
||||
* The default paper size.
|
||||
*
|
||||
* North America standard is "letter"; other countries generally "a4"
|
||||
*
|
||||
* @see CPDF_Adapter::PAPER_SIZES for valid sizes ('letter', 'legal', 'A4', etc.)
|
||||
*/
|
||||
"default_paper_size" => "a4",
|
||||
|
||||
/**
|
||||
* The default paper orientation.
|
||||
*
|
||||
* The orientation of the page (portrait or landscape).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
'default_paper_orientation' => "portrait",
|
||||
|
||||
/**
|
||||
* The default font family
|
||||
*
|
||||
* Used if no suitable fonts can be found. This must exist in the font folder.
|
||||
* @var string
|
||||
*/
|
||||
"default_font" => "serif",
|
||||
|
||||
/**
|
||||
* Image DPI setting
|
||||
*
|
||||
* This setting determines the default DPI setting for images and fonts. The
|
||||
* DPI may be overridden for inline images by explictly setting the
|
||||
* image's width & height style attributes (i.e. if the image's native
|
||||
* width is 600 pixels and you specify the image's width as 72 points,
|
||||
* the image will have a DPI of 600 in the rendered PDF. The DPI of
|
||||
* background images can not be overridden and is controlled entirely
|
||||
* via this parameter.
|
||||
*
|
||||
* For the purposes of DOMPDF, pixels per inch (PPI) = dots per inch (DPI).
|
||||
* If a size in html is given as px (or without unit as image size),
|
||||
* this tells the corresponding size in pt.
|
||||
* This adjusts the relative sizes to be similar to the rendering of the
|
||||
* html page in a reference browser.
|
||||
*
|
||||
* In pdf, always 1 pt = 1/72 inch
|
||||
*
|
||||
* Rendering resolution of various browsers in px per inch:
|
||||
* Windows Firefox and Internet Explorer:
|
||||
* SystemControl->Display properties->FontResolution: Default:96, largefonts:120, custom:?
|
||||
* Linux Firefox:
|
||||
* about:config *resolution: Default:96
|
||||
* (xorg screen dimension in mm and Desktop font dpi settings are ignored)
|
||||
*
|
||||
* Take care about extra font/image zoom factor of browser.
|
||||
*
|
||||
* In images, <img> size in pixel attribute, img css style, are overriding
|
||||
* the real image dimension in px for rendering.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
"dpi" => 96,
|
||||
|
||||
/**
|
||||
* Enable inline PHP
|
||||
*
|
||||
* If this setting is set to true then DOMPDF will automatically evaluate
|
||||
* inline PHP contained within <script type="text/php"> ... </script> tags.
|
||||
*
|
||||
* Enabling this for documents you do not trust (e.g. arbitrary remote html
|
||||
* pages) is a security risk. Set this option to false if you wish to process
|
||||
* untrusted documents.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
"enable_php" => false,
|
||||
|
||||
/**
|
||||
* Enable inline Javascript
|
||||
*
|
||||
* If this setting is set to true then DOMPDF will automatically insert
|
||||
* JavaScript code contained within <script type="text/javascript"> ... </script> tags.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
"enable_javascript" => true,
|
||||
|
||||
/**
|
||||
* Enable remote file access
|
||||
*
|
||||
* If this setting is set to true, DOMPDF will access remote sites for
|
||||
* images and CSS files as required.
|
||||
* This is required for part of test case www/test/image_variants.html through www/examples.php
|
||||
*
|
||||
* Attention!
|
||||
* This can be a security risk, in particular in combination with DOMPDF_ENABLE_PHP and
|
||||
* allowing remote access to dompdf.php or on allowing remote html code to be passed to
|
||||
* $dompdf = new DOMPDF(, $dompdf->load_html(...,
|
||||
* This allows anonymous users to download legally doubtful internet content which on
|
||||
* tracing back appears to being downloaded by your server, or allows malicious php code
|
||||
* in remote html pages to be executed by your server with your account privileges.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
"enable_remote" => true,
|
||||
|
||||
/**
|
||||
* A ratio applied to the fonts height to be more like browsers' line height
|
||||
*/
|
||||
"font_height_ratio" => 1.1,
|
||||
|
||||
/**
|
||||
* Use the HTML5 Lib parser
|
||||
*
|
||||
* @deprecated This feature is now always on in dompdf 2.x
|
||||
* @var bool
|
||||
*/
|
||||
"enable_html5_parser" => true,
|
||||
),
|
||||
|
||||
|
||||
);
|
||||
@@ -0,0 +1,130 @@
|
||||
## DOMPDF Wrapper for Laravel
|
||||
|
||||
### Laravel wrapper for [Dompdf HTML to PDF Converter](https://github.com/dompdf/dompdf)
|
||||
|
||||
[](https://github.com/barryvdh/laravel-dompdf/actions)
|
||||
[](http://choosealicense.com/licenses/mit/)
|
||||
[](https://packagist.org/packages/barryvdh/laravel-dompdf)
|
||||
[](https://packagist.org/packages/barryvdh/laravel-dompdf)
|
||||
[](https://fruitcake.nl/)
|
||||
|
||||
## Installation
|
||||
|
||||
### Laravel
|
||||
Require this package in your composer.json and update composer. This will download the package and the dompdf + fontlib libraries also.
|
||||
|
||||
composer require barryvdh/laravel-dompdf
|
||||
|
||||
### Lumen
|
||||
|
||||
After updating composer add the following lines to register provider in `bootstrap/app.php`
|
||||
|
||||
```
|
||||
$app->register(\Barryvdh\DomPDF\ServiceProvider::class);
|
||||
```
|
||||
|
||||
To change the configuration, copy the config file to your config folder and enable it in `bootstrap/app.php`:
|
||||
|
||||
```
|
||||
$app->configure('dompdf');
|
||||
```
|
||||
|
||||
## Using
|
||||
|
||||
You can create a new DOMPDF instance and load a HTML string, file or view name. You can save it to a file, or stream (show in browser) or download.
|
||||
|
||||
```php
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
|
||||
$pdf = Pdf::loadView('pdf.invoice', $data);
|
||||
return $pdf->download('invoice.pdf');
|
||||
```
|
||||
|
||||
or use the App container:
|
||||
|
||||
```php
|
||||
$pdf = App::make('dompdf.wrapper');
|
||||
$pdf->loadHTML('<h1>Test</h1>');
|
||||
return $pdf->stream();
|
||||
```
|
||||
|
||||
Or use the facade:
|
||||
|
||||
You can chain the methods:
|
||||
|
||||
```php
|
||||
return Pdf::loadFile(public_path().'/myfile.html')->save('/path-to/my_stored_file.pdf')->stream('download.pdf');
|
||||
```
|
||||
|
||||
You can change the orientation and paper size, and hide or show errors (by default, errors are shown when debug is on)
|
||||
|
||||
```php
|
||||
Pdf::loadHTML($html)->setPaper('a4', 'landscape')->setWarnings(false)->save('myfile.pdf')
|
||||
```
|
||||
|
||||
If you need the output as a string, you can get the rendered PDF with the output() function, so you can save/output it yourself.
|
||||
|
||||
Use `php artisan vendor:publish` to create a config file located at `config/dompdf.php` which will allow you to define local configurations to change some settings (default paper etc).
|
||||
You can also use your ConfigProvider to set certain keys.
|
||||
|
||||
### Configuration
|
||||
The defaults configuration settings are set in `config/dompdf.php`. Copy this file to your own config directory to modify the values. You can publish the config using this command:
|
||||
```shell
|
||||
php artisan vendor:publish --provider="Barryvdh\DomPDF\ServiceProvider"
|
||||
```
|
||||
|
||||
You can still alter the dompdf options in your code before generating the pdf using this command:
|
||||
```php
|
||||
Pdf::setOption(['dpi' => 150, 'defaultFont' => 'sans-serif']);
|
||||
```
|
||||
|
||||
Available options and their defaults:
|
||||
* __rootDir__: "{app_directory}/vendor/dompdf/dompdf"
|
||||
* __tempDir__: "/tmp" _(available in config/dompdf.php)_
|
||||
* __fontDir__: "{app_directory}/storage/fonts" _(available in config/dompdf.php)_
|
||||
* __fontCache__: "{app_directory}/storage/fonts" _(available in config/dompdf.php)_
|
||||
* __chroot__: "{app_directory}" _(available in config/dompdf.php)_
|
||||
* __logOutputFile__: "/tmp/log.htm"
|
||||
* __defaultMediaType__: "screen" _(available in config/dompdf.php)_
|
||||
* __defaultPaperSize__: "a4" _(available in config/dompdf.php)_
|
||||
* __defaultFont__: "serif" _(available in config/dompdf.php)_
|
||||
* __dpi__: 96 _(available in config/dompdf.php)_
|
||||
* __fontHeightRatio__: 1.1 _(available in config/dompdf.php)_
|
||||
* __isPhpEnabled__: false _(available in config/dompdf.php)_
|
||||
* __isRemoteEnabled__: true _(available in config/dompdf.php)_
|
||||
* __isJavascriptEnabled__: true _(available in config/dompdf.php)_
|
||||
* __isHtml5ParserEnabled__: false _(available in config/dompdf.php)_
|
||||
* __isFontSubsettingEnabled__: false _(available in config/dompdf.php)_
|
||||
* __debugPng__: false
|
||||
* __debugKeepTemp__: false
|
||||
* __debugCss__: false
|
||||
* __debugLayout__: false
|
||||
* __debugLayoutLines__: true
|
||||
* __debugLayoutBlocks__: true
|
||||
* __debugLayoutInline__: true
|
||||
* __debugLayoutPaddingBox__: true
|
||||
* __pdfBackend__: "CPDF" _(available in config/dompdf.php)_
|
||||
* __pdflibLicense__: ""
|
||||
* __adminUsername__: "user"
|
||||
* __adminPassword__: "password"
|
||||
|
||||
### Tip: UTF-8 support
|
||||
In your templates, set the UTF-8 Metatag:
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
|
||||
### Tip: Page breaks
|
||||
You can use the CSS `page-break-before`/`page-break-after` properties to create a new page.
|
||||
|
||||
<style>
|
||||
.page-break {
|
||||
page-break-after: always;
|
||||
}
|
||||
</style>
|
||||
<h1>Page 1</h1>
|
||||
<div class="page-break"></div>
|
||||
<h1>Page 2</h1>
|
||||
|
||||
### License
|
||||
|
||||
This DOMPDF Wrapper for Laravel is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\DomPDF\Facade;
|
||||
|
||||
use Barryvdh\DomPDF\PDF as BasePDF;
|
||||
use Illuminate\Support\Facades\Facade as IlluminateFacade;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* @method static BasePDF setBaseHost(string $baseHost)
|
||||
* @method static BasePDF setBasePath(string $basePath)
|
||||
* @method static BasePDF setCanvas(\Dompdf\Canvas $canvas)
|
||||
* @method static BasePDF setCallbacks(array $callbacks)
|
||||
* @method static BasePDF setCss(\Dompdf\Css\Stylesheet $css)
|
||||
* @method static BasePDF setDefaultView(string $defaultView, array $options)
|
||||
* @method static BasePDF setDom(\DOMDocument $dom)
|
||||
* @method static BasePDF setFontMetrics(\Dompdf\FontMetrics $fontMetrics)
|
||||
* @method static BasePDF setHttpContext(resource|array $httpContext)
|
||||
* @method static BasePDF setPaper(string|float[] $paper, string $orientation = 'portrait')
|
||||
* @method static BasePDF setProtocol(string $protocol)
|
||||
* @method static BasePDF setTree(\Dompdf\Frame\FrameTree $tree)
|
||||
* @method static BasePDF setWarnings(bool $warnings)
|
||||
* @method static BasePDF setOption(array|string $attribute, $value = null)
|
||||
* @method static BasePDF setOptions(array $options)
|
||||
* @method static BasePDF loadView(string $view, array $data = [], array $mergeData = [], ?string $encoding = null)
|
||||
* @method static BasePDF loadHTML(string $string, ?string $encoding = null)
|
||||
* @method static BasePDF loadFile(string $file)
|
||||
* @method static BasePDF addInfo(array $info)
|
||||
* @method static string output(array $options = [])
|
||||
* @method static BasePDF save()
|
||||
* @method static \Illuminate\Http\Response download(string $filename = 'document.pdf')
|
||||
* @method static \Illuminate\Http\Response stream(string $filename = 'document.pdf')
|
||||
*/
|
||||
class Pdf extends IlluminateFacade
|
||||
{
|
||||
/**
|
||||
* Get the registered name of the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getFacadeAccessor()
|
||||
{
|
||||
return 'dompdf.wrapper';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dynamic, static calls to the object.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array<mixed> $args
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public static function __callStatic($method, $args)
|
||||
{
|
||||
/** @var \Illuminate\Contracts\Foundation\Application|null */
|
||||
$app = static::getFacadeApplication();
|
||||
if (! $app) {
|
||||
throw new RuntimeException('Facade application has not been set.');
|
||||
}
|
||||
|
||||
// Resolve a new instance, avoid using a cached instance
|
||||
$instance = $app->make(static::getFacadeAccessor());
|
||||
|
||||
return $instance->$method(...$args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\DomPDF;
|
||||
|
||||
use Dompdf\Adapter\CPDF;
|
||||
use Dompdf\Dompdf;
|
||||
use Dompdf\Options;
|
||||
use Exception;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Contracts\View\Factory as ViewFactory;
|
||||
use Illuminate\Contracts\Config\Repository as ConfigRepository;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/**
|
||||
* A Laravel wrapper for Dompdf
|
||||
*
|
||||
* @package laravel-dompdf
|
||||
* @author Barry vd. Heuvel
|
||||
*
|
||||
* @method PDF setBaseHost(string $baseHost)
|
||||
* @method PDF setBasePath(string $basePath)
|
||||
* @method PDF setCanvas(\Dompdf\Canvas $canvas)
|
||||
* @method PDF setCallbacks(array $callbacks)
|
||||
* @method PDF setCss(\Dompdf\Css\Stylesheet $css)
|
||||
* @method PDF setDefaultView(string $defaultView, array $options)
|
||||
* @method PDF setDom(\DOMDocument $dom)
|
||||
* @method PDF setFontMetrics(\Dompdf\FontMetrics $fontMetrics)
|
||||
* @method PDF setHttpContext(resource|array $httpContext)
|
||||
* @method PDF setPaper(string|float[] $paper, string $orientation = 'portrait')
|
||||
* @method PDF setProtocol(string $protocol)
|
||||
* @method PDF setTree(\Dompdf\Frame\FrameTree $tree)
|
||||
* @method string getBaseHost()
|
||||
* @method string getBasePath()
|
||||
* @method \Dompdf\Canvas getCanvas()
|
||||
* @method array getCallbacks()
|
||||
* @method \Dompdf\Css\Stylesheet getCss()
|
||||
* @method \DOMDocument getDom()
|
||||
* @method \Dompdf\FontMetrics getFontMetrics()
|
||||
* @method resource getHttpContext()
|
||||
* @method Options getOptions()
|
||||
* @method \Dompdf\Frame\FrameTree getTree()
|
||||
* @method string getPaperOrientation()
|
||||
* @method float[] getPaperSize()
|
||||
* @method string getProtocol()
|
||||
*/
|
||||
class PDF
|
||||
{
|
||||
/** @var Dompdf */
|
||||
protected $dompdf;
|
||||
|
||||
/** @var \Illuminate\Contracts\Config\Repository */
|
||||
protected $config;
|
||||
|
||||
/** @var \Illuminate\Filesystem\Filesystem */
|
||||
protected $files;
|
||||
|
||||
/** @var \Illuminate\Contracts\View\Factory */
|
||||
protected $view;
|
||||
|
||||
/** @var bool */
|
||||
protected $rendered = false;
|
||||
|
||||
/** @var bool */
|
||||
protected $showWarnings;
|
||||
|
||||
/** @var string */
|
||||
protected $public_path;
|
||||
|
||||
public function __construct(Dompdf $dompdf, ConfigRepository $config, Filesystem $files, ViewFactory $view)
|
||||
{
|
||||
$this->dompdf = $dompdf;
|
||||
$this->config = $config;
|
||||
$this->files = $files;
|
||||
$this->view = $view;
|
||||
|
||||
$this->showWarnings = $this->config->get('dompdf.show_warnings', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DomPDF instance
|
||||
*/
|
||||
public function getDomPDF(): Dompdf
|
||||
{
|
||||
return $this->dompdf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show or hide warnings
|
||||
*/
|
||||
public function setWarnings(bool $warnings): self
|
||||
{
|
||||
$this->showWarnings = $warnings;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a HTML string
|
||||
*
|
||||
* @param string|null $encoding Not used yet
|
||||
*/
|
||||
public function loadHTML(string $string, ?string $encoding = null): self
|
||||
{
|
||||
$string = $this->convertEntities($string);
|
||||
$this->dompdf->loadHtml($string, $encoding);
|
||||
$this->rendered = false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a HTML file
|
||||
*/
|
||||
public function loadFile(string $file): self
|
||||
{
|
||||
$this->dompdf->loadHtmlFile($file);
|
||||
$this->rendered = false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add metadata info
|
||||
* @param array<string, string> $info
|
||||
*/
|
||||
public function addInfo(array $info): self
|
||||
{
|
||||
foreach ($info as $name => $value) {
|
||||
$this->dompdf->add_info($name, $value);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a View and convert to HTML
|
||||
* @param array<string, mixed> $data
|
||||
* @param array<string, mixed> $mergeData
|
||||
* @param string|null $encoding Not used yet
|
||||
*/
|
||||
public function loadView(string $view, array $data = [], array $mergeData = [], ?string $encoding = null): self
|
||||
{
|
||||
$html = $this->view->make($view, $data, $mergeData)->render();
|
||||
return $this->loadHTML($html, $encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set/Change an option (or array of options) in Dompdf
|
||||
*
|
||||
* @param array<string, mixed>|string $attribute
|
||||
* @param null|mixed $value
|
||||
*/
|
||||
public function setOption($attribute, $value = null): self
|
||||
{
|
||||
$this->dompdf->getOptions()->set($attribute, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all the Options from DomPDF
|
||||
*
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
public function setOptions(array $options, bool $mergeWithDefaults = false): self
|
||||
{
|
||||
if ($mergeWithDefaults) {
|
||||
$options = array_merge(app()->make('dompdf.options'), $options);
|
||||
}
|
||||
|
||||
$this->dompdf->setOptions(new Options($options));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the PDF as a string.
|
||||
*
|
||||
* The options parameter controls the output. Accepted options are:
|
||||
*
|
||||
* 'compress' = > 1 or 0 - apply content stream compression, this is
|
||||
* on (1) by default
|
||||
*
|
||||
* @param array<string, int> $options
|
||||
*
|
||||
* @return string The rendered PDF as string
|
||||
*/
|
||||
public function output(array $options = []): string
|
||||
{
|
||||
if (!$this->rendered) {
|
||||
$this->render();
|
||||
}
|
||||
return (string) $this->dompdf->output($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the PDF to a file
|
||||
*/
|
||||
public function save(string $filename, string $disk = null): self
|
||||
{
|
||||
$disk = $disk ?: $this->config->get('dompdf.disk');
|
||||
|
||||
if (! is_null($disk)) {
|
||||
Storage::disk($disk)->put($filename, $this->output());
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->files->put($filename, $this->output());
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the PDF downloadable by the user
|
||||
*/
|
||||
public function download(string $filename = 'document.pdf'): Response
|
||||
{
|
||||
$output = $this->output();
|
||||
return new Response($output, 200, [
|
||||
'Content-Type' => 'application/pdf',
|
||||
'Content-Disposition' => 'attachment; filename="' . $filename . '"',
|
||||
'Content-Length' => strlen($output),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a response with the PDF to show in the browser
|
||||
*/
|
||||
public function stream(string $filename = 'document.pdf'): Response
|
||||
{
|
||||
$output = $this->output();
|
||||
return new Response($output, 200, [
|
||||
'Content-Type' => 'application/pdf',
|
||||
'Content-Disposition' => 'inline; filename="' . $filename . '"',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the PDF
|
||||
*/
|
||||
public function render(): void
|
||||
{
|
||||
$this->dompdf->render();
|
||||
|
||||
if ($this->showWarnings) {
|
||||
global $_dompdf_warnings;
|
||||
if (!empty($_dompdf_warnings) && count($_dompdf_warnings)) {
|
||||
$warnings = '';
|
||||
foreach ($_dompdf_warnings as $msg) {
|
||||
$warnings .= $msg . "\n";
|
||||
}
|
||||
// $warnings .= $this->dompdf->get_canvas()->get_cpdf()->messages;
|
||||
if (!empty($warnings)) {
|
||||
throw new Exception($warnings);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->rendered = true;
|
||||
}
|
||||
|
||||
/** @param array<string> $pc */
|
||||
public function setEncryption(string $password, string $ownerpassword = '', array $pc = []): void
|
||||
{
|
||||
$this->render();
|
||||
$canvas = $this->dompdf->getCanvas();
|
||||
if (! $canvas instanceof CPDF) {
|
||||
throw new \RuntimeException('Encryption is only supported when using CPDF');
|
||||
}
|
||||
$canvas->get_cpdf()->setEncryption($password, $ownerpassword, $pc);
|
||||
}
|
||||
|
||||
protected function convertEntities(string $subject): string
|
||||
{
|
||||
if (false === $this->config->get('dompdf.convert_entities', true)) {
|
||||
return $subject;
|
||||
}
|
||||
|
||||
$entities = [
|
||||
'€' => '€',
|
||||
'£' => '£',
|
||||
];
|
||||
|
||||
foreach ($entities as $search => $replace) {
|
||||
$subject = str_replace($search, $replace, $subject);
|
||||
}
|
||||
return $subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically handle calls into the dompdf instance.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array<mixed> $parameters
|
||||
* @return $this|mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
if (method_exists($this, $method)) {
|
||||
return $this->$method(...$parameters);
|
||||
}
|
||||
|
||||
if (method_exists($this->dompdf, $method)) {
|
||||
$return = $this->dompdf->$method(...$parameters);
|
||||
|
||||
return $return == $this->dompdf ? $this : $return;
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException("Method [{$method}] does not exist on PDF instance.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Barryvdh\DomPDF;
|
||||
|
||||
use Dompdf\Dompdf;
|
||||
use Exception;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\ServiceProvider as IlluminateServiceProvider;
|
||||
|
||||
class ServiceProvider extends IlluminateServiceProvider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = false;
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @throws \Exception
|
||||
* @return void
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
$configPath = __DIR__ . '/../config/dompdf.php';
|
||||
$this->mergeConfigFrom($configPath, 'dompdf');
|
||||
|
||||
$this->app->bind('dompdf.options', function ($app) {
|
||||
$defines = $app['config']->get('dompdf.defines');
|
||||
|
||||
if ($defines) {
|
||||
$options = [];
|
||||
/**
|
||||
* @var string $key
|
||||
* @var mixed $value
|
||||
*/
|
||||
foreach ($defines as $key => $value) {
|
||||
$key = strtolower(str_replace('DOMPDF_', '', $key));
|
||||
$options[$key] = $value;
|
||||
}
|
||||
} else {
|
||||
$options = $app['config']->get('dompdf.options');
|
||||
}
|
||||
|
||||
return $options;
|
||||
});
|
||||
|
||||
$this->app->bind('dompdf', function ($app) {
|
||||
|
||||
$options = $app->make('dompdf.options');
|
||||
$dompdf = new Dompdf($options);
|
||||
$path = realpath($app['config']->get('dompdf.public_path') ?: base_path('public'));
|
||||
if ($path === false) {
|
||||
throw new \RuntimeException('Cannot resolve public path');
|
||||
}
|
||||
$dompdf->setBasePath($path);
|
||||
|
||||
return $dompdf;
|
||||
});
|
||||
$this->app->alias('dompdf', Dompdf::class);
|
||||
|
||||
$this->app->bind('dompdf.wrapper', function ($app) {
|
||||
return new PDF($app['dompdf'], $app['config'], $app['files'], $app['view']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if package is running under Lumen app
|
||||
*/
|
||||
protected function isLumen(): bool
|
||||
{
|
||||
return Str::contains($this->app->version(), 'Lumen') === true;
|
||||
}
|
||||
|
||||
public function boot(): void
|
||||
{
|
||||
if (! $this->isLumen()) {
|
||||
$configPath = __DIR__ . '/../config/dompdf.php';
|
||||
$this->publishes([$configPath => config_path('dompdf.php')], 'config');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
public function provides(): array
|
||||
{
|
||||
return ['dompdf', 'dompdf.options', 'dompdf.wrapper'];
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,14 @@
|
||||
{
|
||||
"name": "barryvdh/laravel-snappy",
|
||||
"description": "Snappy PDF/Image for Laravel",
|
||||
"keywords": ["laravel","snappy", "pdf", "image", "wkhtmltopdf", "wkhtmltoimage"],
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"snappy",
|
||||
"pdf",
|
||||
"image",
|
||||
"wkhtmltopdf",
|
||||
"wkhtmltoimage"
|
||||
],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
@@ -11,12 +18,12 @@
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"illuminate/support": "^9|^10",
|
||||
"illuminate/filesystem": "^9|^10",
|
||||
"knplabs/knp-snappy": "^1.4"
|
||||
"illuminate/support": "^9|^10|^11.0",
|
||||
"illuminate/filesystem": "^9|^10|^11.0",
|
||||
"knplabs/knp-snappy": "^1.4.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"orchestra/testbench": "^7|^8"
|
||||
"orchestra/testbench": "^7|^8|^9.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
@@ -17,7 +17,7 @@ return [
|
||||
|
|
||||
| The file path of the wkhtmltopdf / wkhtmltoimage executable.
|
||||
|
|
||||
| Timout:
|
||||
| Timeout:
|
||||
|
|
||||
| The amount of time to wait (in seconds) before PDF / Image generation is stopped.
|
||||
| Setting this to false disables the timeout (unlimited processing time).
|
||||
|
||||
+4
@@ -4,6 +4,10 @@ use Knp\Snappy\Image;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
|
||||
class IlluminateSnappyImage extends Image {
|
||||
/**
|
||||
* @var \Illuminate\Filesystem\Filesystem
|
||||
*/
|
||||
protected $fs;
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Filesystem\Filesystem
|
||||
|
||||
@@ -23,6 +23,15 @@ class ImageWrapper {
|
||||
*/
|
||||
protected $options = array();
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $html;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* @param \Knp\Snappy\Image $snappy
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../phpmyadmin/sql-parser/bin/highlight-query)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/phpmyadmin/sql-parser/bin/highlight-query');
|
||||
}
|
||||
}
|
||||
|
||||
return include __DIR__ . '/..'.'/phpmyadmin/sql-parser/bin/highlight-query';
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../phpmyadmin/sql-parser/bin/lint-query)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/phpmyadmin/sql-parser/bin/lint-query');
|
||||
}
|
||||
}
|
||||
|
||||
return include __DIR__ . '/..'.'/phpmyadmin/sql-parser/bin/lint-query';
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../phpmyadmin/sql-parser/bin/sql-parser)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/phpmyadmin/sql-parser/bin/sql-parser');
|
||||
}
|
||||
}
|
||||
|
||||
return include __DIR__ . '/..'.'/phpmyadmin/sql-parser/bin/sql-parser';
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../phpmyadmin/sql-parser/bin/tokenize-query)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/phpmyadmin/sql-parser/bin/tokenize-query');
|
||||
}
|
||||
}
|
||||
|
||||
return include __DIR__ . '/..'.'/phpmyadmin/sql-parser/bin/tokenize-query';
|
||||
+1
-1
@@ -34,4 +34,4 @@ if [ -n "$bashSource" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
"${dir}/wkhtmltoimage-amd64" "$@"
|
||||
exec "${dir}/wkhtmltoimage-amd64" "$@"
|
||||
|
||||
+1
-1
@@ -34,4 +34,4 @@ if [ -n "$bashSource" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
"${dir}/wkhtmltopdf-amd64" "$@"
|
||||
exec "${dir}/wkhtmltopdf-amd64" "$@"
|
||||
|
||||
@@ -2,6 +2,24 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [0.12.1](https://github.com/brick/math/releases/tag/0.12.1) - 2023-11-29
|
||||
|
||||
⚡️ **Performance improvements**
|
||||
|
||||
- `BigNumber::of()` is now faster, thanks to [@SebastienDug](https://github.com/SebastienDug) in [#77](https://github.com/brick/math/pull/77).
|
||||
|
||||
## [0.12.0](https://github.com/brick/math/releases/tag/0.12.0) - 2023-11-26
|
||||
|
||||
💥 **Breaking changes**
|
||||
|
||||
- Minimum PHP version is now 8.1
|
||||
- `RoundingMode` is now an `enum`; if you're type-hinting rounding modes, you need to type-hint against `RoundingMode` instead of `int` now
|
||||
- `BigNumber` classes do not implement the `Serializable` interface anymore (they use the [new custom object serialization mechanism](https://wiki.php.net/rfc/custom_object_serialization))
|
||||
- The following breaking changes only affect you if you're creating your own `BigNumber` subclasses:
|
||||
- the return type of `BigNumber::of()` is now `static`
|
||||
- `BigNumber` has a new abstract method `from()`
|
||||
- all `public` and `protected` functions of `BigNumber` are now `final`
|
||||
|
||||
## [0.11.0](https://github.com/brick/math/releases/tag/0.11.0) - 2023-01-16
|
||||
|
||||
💥 **Breaking changes**
|
||||
|
||||
+9
-4
@@ -5,21 +5,26 @@
|
||||
"keywords": [
|
||||
"Brick",
|
||||
"Math",
|
||||
"Mathematics",
|
||||
"Arbitrary-precision",
|
||||
"Arithmetic",
|
||||
"BigInteger",
|
||||
"BigDecimal",
|
||||
"BigRational",
|
||||
"Bignum"
|
||||
"BigNumber",
|
||||
"Bignum",
|
||||
"Decimal",
|
||||
"Rational",
|
||||
"Integer"
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.0"
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.0",
|
||||
"phpunit/phpunit": "^10.1",
|
||||
"php-coveralls/php-coveralls": "^2.2",
|
||||
"vimeo/psalm": "5.0.0"
|
||||
"vimeo/psalm": "5.16.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
+11
-43
@@ -23,14 +23,14 @@ final class BigDecimal extends BigNumber
|
||||
* No leading zero must be present.
|
||||
* No leading minus sign must be present if the value is 0.
|
||||
*/
|
||||
private string $value;
|
||||
private readonly string $value;
|
||||
|
||||
/**
|
||||
* The scale (number of digits after the decimal point) of this decimal number.
|
||||
*
|
||||
* This must be zero or more.
|
||||
*/
|
||||
private int $scale;
|
||||
private readonly int $scale;
|
||||
|
||||
/**
|
||||
* Protected constructor. Use a factory method to obtain an instance.
|
||||
@@ -45,15 +45,11 @@ final class BigDecimal extends BigNumber
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigDecimal of the given value.
|
||||
*
|
||||
* @throws MathException If the value cannot be converted to a BigDecimal.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of(BigNumber|int|float|string $value) : BigDecimal
|
||||
protected static function from(BigNumber $number): static
|
||||
{
|
||||
return parent::of($value)->toBigDecimal();
|
||||
return $number->toBigDecimal();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,12 +219,12 @@ final class BigDecimal extends BigNumber
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor.
|
||||
* @param int|null $scale The desired scale, or null to use the scale of this number.
|
||||
* @param int $roundingMode An optional rounding mode.
|
||||
* @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
|
||||
*
|
||||
* @throws \InvalidArgumentException If the scale or rounding mode is invalid.
|
||||
* @throws MathException If the number is invalid, is zero, or rounding was necessary.
|
||||
*/
|
||||
public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
@@ -324,7 +320,7 @@ final class BigDecimal extends BigNumber
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient of the division of this number by this given one.
|
||||
* Returns the quotient of the division of this number by the given one.
|
||||
*
|
||||
* The quotient has a scale of `0`.
|
||||
*
|
||||
@@ -349,7 +345,7 @@ final class BigDecimal extends BigNumber
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remainder of the division of this number by this given one.
|
||||
* Returns the remainder of the division of this number by the given one.
|
||||
*
|
||||
* The remainder has a scale of `max($this->scale, $that->scale)`.
|
||||
*
|
||||
@@ -384,6 +380,8 @@ final class BigDecimal extends BigNumber
|
||||
*
|
||||
* @return BigDecimal[] An array containing the quotient and the remainder.
|
||||
*
|
||||
* @psalm-return array{BigDecimal, BigDecimal}
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
*/
|
||||
public function quotientAndRemainder(BigNumber|int|float|string $that) : array
|
||||
@@ -631,7 +629,7 @@ final class BigDecimal extends BigNumber
|
||||
return self::newBigRational($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
if ($scale === $this->scale) {
|
||||
return $this;
|
||||
@@ -693,36 +691,6 @@ final class BigDecimal extends BigNumber
|
||||
$this->scale = $data['scale'];
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required by interface Serializable and SHOULD NOT be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function serialize() : string
|
||||
{
|
||||
return $this->value . ':' . $this->scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only here to implement interface Serializable and cannot be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
* @psalm-suppress RedundantPropertyInitializationCheck
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function unserialize($value) : void
|
||||
{
|
||||
if (isset($this->value)) {
|
||||
throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
|
||||
}
|
||||
|
||||
[$value, $scale] = \explode(':', $value);
|
||||
|
||||
$this->value = $value;
|
||||
$this->scale = (int) $scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the internal values of the given decimal numbers on the same scale.
|
||||
*
|
||||
|
||||
+10
-38
@@ -27,7 +27,7 @@ final class BigInteger extends BigNumber
|
||||
* No leading zeros must be present.
|
||||
* No leading minus sign must be present if the number is zero.
|
||||
*/
|
||||
private string $value;
|
||||
private readonly string $value;
|
||||
|
||||
/**
|
||||
* Protected constructor. Use a factory method to obtain an instance.
|
||||
@@ -40,15 +40,11 @@ final class BigInteger extends BigNumber
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigInteger of the given value.
|
||||
*
|
||||
* @throws MathException If the value cannot be converted to a BigInteger.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of(BigNumber|int|float|string $value) : BigInteger
|
||||
protected static function from(BigNumber $number): static
|
||||
{
|
||||
return parent::of($value)->toBigInteger();
|
||||
return $number->toBigInteger();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,9 +221,10 @@ final class BigInteger extends BigNumber
|
||||
}
|
||||
|
||||
if ($randomBytesGenerator === null) {
|
||||
$randomBytesGenerator = 'random_bytes';
|
||||
$randomBytesGenerator = random_bytes(...);
|
||||
}
|
||||
|
||||
/** @var int<1, max> $byteLength */
|
||||
$byteLength = \intdiv($numBits - 1, 8) + 1;
|
||||
|
||||
$extraBits = ($byteLength * 8 - $numBits);
|
||||
@@ -429,12 +426,12 @@ final class BigInteger extends BigNumber
|
||||
* Returns the result of the division of this number by the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||
* @param int $roundingMode An optional rounding mode.
|
||||
* @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid number, is not convertible to a BigInteger, is zero,
|
||||
* or RoundingMode::UNNECESSARY is used and the remainder is not zero.
|
||||
*/
|
||||
public function dividedBy(BigNumber|int|float|string $that, int $roundingMode = RoundingMode::UNNECESSARY) : BigInteger
|
||||
public function dividedBy(BigNumber|int|float|string $that, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigInteger
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
@@ -534,6 +531,8 @@ final class BigInteger extends BigNumber
|
||||
*
|
||||
* @return BigInteger[] An array containing the quotient and the remainder.
|
||||
*
|
||||
* @psalm-return array{BigInteger, BigInteger}
|
||||
*
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
*/
|
||||
public function quotientAndRemainder(BigNumber|int|float|string $that) : array
|
||||
@@ -888,7 +887,7 @@ final class BigInteger extends BigNumber
|
||||
return self::newBigRational($this, BigInteger::one(), false);
|
||||
}
|
||||
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
return $this->toBigDecimal()->toScale($scale, $roundingMode);
|
||||
}
|
||||
@@ -1049,31 +1048,4 @@ final class BigInteger extends BigNumber
|
||||
|
||||
$this->value = $data['value'];
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required by interface Serializable and SHOULD NOT be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function serialize() : string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only here to implement interface Serializable and cannot be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
* @psalm-suppress RedundantPropertyInitializationCheck
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function unserialize($value) : void
|
||||
{
|
||||
if (isset($this->value)) {
|
||||
throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
|
||||
}
|
||||
|
||||
$this->value = $value;
|
||||
}
|
||||
}
|
||||
|
||||
+122
-125
@@ -14,26 +14,29 @@ use Brick\Math\Exception\RoundingNecessaryException;
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
abstract class BigNumber implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* The regular expression used to parse integer, decimal and rational numbers.
|
||||
* The regular expression used to parse integer or decimal numbers.
|
||||
*/
|
||||
private const PARSE_REGEXP =
|
||||
private const PARSE_REGEXP_NUMERICAL =
|
||||
'/^' .
|
||||
'(?<sign>[\-\+])?' .
|
||||
'(?:' .
|
||||
'(?:' .
|
||||
'(?<integral>[0-9]+)?' .
|
||||
'(?<point>\.)?' .
|
||||
'(?<fractional>[0-9]+)?' .
|
||||
'(?:[eE](?<exponent>[\-\+]?[0-9]+))?' .
|
||||
')|(?:' .
|
||||
'(?<numerator>[0-9]+)' .
|
||||
'\/?' .
|
||||
'(?<denominator>[0-9]+)' .
|
||||
')' .
|
||||
')' .
|
||||
'(?<integral>[0-9]+)?' .
|
||||
'(?<point>\.)?' .
|
||||
'(?<fractional>[0-9]+)?' .
|
||||
'(?:[eE](?<exponent>[\-\+]?[0-9]+))?' .
|
||||
'$/';
|
||||
|
||||
/**
|
||||
* The regular expression used to parse rational numbers.
|
||||
*/
|
||||
private const PARSE_REGEXP_RATIONAL =
|
||||
'/^' .
|
||||
'(?<sign>[\-\+])?' .
|
||||
'(?<numerator>[0-9]+)' .
|
||||
'\/?' .
|
||||
'(?<denominator>[0-9]+)' .
|
||||
'$/';
|
||||
|
||||
/**
|
||||
@@ -53,7 +56,24 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of(BigNumber|int|float|string $value) : BigNumber
|
||||
final public static function of(BigNumber|int|float|string $value) : static
|
||||
{
|
||||
$value = self::_of($value);
|
||||
|
||||
if (static::class === BigNumber::class) {
|
||||
// https://github.com/vimeo/psalm/issues/10309
|
||||
assert($value instanceof static);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
return static::from($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-pure
|
||||
*/
|
||||
private static function _of(BigNumber|int|float|string $value) : BigNumber
|
||||
{
|
||||
if ($value instanceof BigNumber) {
|
||||
return $value;
|
||||
@@ -63,34 +83,25 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
return new BigInteger((string) $value);
|
||||
}
|
||||
|
||||
$value = \is_float($value) ? self::floatToString($value) : $value;
|
||||
|
||||
$throw = static function() use ($value) : void {
|
||||
throw new NumberFormatException(\sprintf(
|
||||
'The given value "%s" does not represent a valid number.',
|
||||
$value
|
||||
));
|
||||
};
|
||||
|
||||
if (\preg_match(self::PARSE_REGEXP, $value, $matches) !== 1) {
|
||||
$throw();
|
||||
if (is_float($value)) {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
||||
$getMatch = static fn(string $value): ?string => (($matches[$value] ?? '') !== '') ? $matches[$value] : null;
|
||||
|
||||
$sign = $getMatch('sign');
|
||||
$numerator = $getMatch('numerator');
|
||||
$denominator = $getMatch('denominator');
|
||||
|
||||
if ($numerator !== null) {
|
||||
assert($denominator !== null);
|
||||
|
||||
if ($sign !== null) {
|
||||
$numerator = $sign . $numerator;
|
||||
if (str_contains($value, '/')) {
|
||||
// Rational number
|
||||
if (\preg_match(self::PARSE_REGEXP_RATIONAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) {
|
||||
throw NumberFormatException::invalidFormat($value);
|
||||
}
|
||||
|
||||
$numerator = self::cleanUp($numerator);
|
||||
$denominator = self::cleanUp($denominator);
|
||||
$sign = $matches['sign'];
|
||||
$numerator = $matches['numerator'];
|
||||
$denominator = $matches['denominator'];
|
||||
|
||||
assert($numerator !== null);
|
||||
assert($denominator !== null);
|
||||
|
||||
$numerator = self::cleanUp($sign, $numerator);
|
||||
$denominator = self::cleanUp(null, $denominator);
|
||||
|
||||
if ($denominator === '0') {
|
||||
throw DivisionByZeroException::denominatorMustNotBeZero();
|
||||
@@ -101,67 +112,62 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
new BigInteger($denominator),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
$point = $getMatch('point');
|
||||
$integral = $getMatch('integral');
|
||||
$fractional = $getMatch('fractional');
|
||||
$exponent = $getMatch('exponent');
|
||||
|
||||
if ($integral === null && $fractional === null) {
|
||||
$throw();
|
||||
}
|
||||
|
||||
if ($integral === null) {
|
||||
$integral = '0';
|
||||
}
|
||||
|
||||
if ($point !== null || $exponent !== null) {
|
||||
$fractional = ($fractional ?? '');
|
||||
$exponent = ($exponent !== null) ? (int) $exponent : 0;
|
||||
|
||||
if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) {
|
||||
throw new NumberFormatException('Exponent too large.');
|
||||
} else {
|
||||
// Integer or decimal number
|
||||
if (\preg_match(self::PARSE_REGEXP_NUMERICAL, $value, $matches, PREG_UNMATCHED_AS_NULL) !== 1) {
|
||||
throw NumberFormatException::invalidFormat($value);
|
||||
}
|
||||
|
||||
$unscaledValue = self::cleanUp(($sign ?? ''). $integral . $fractional);
|
||||
$sign = $matches['sign'];
|
||||
$point = $matches['point'];
|
||||
$integral = $matches['integral'];
|
||||
$fractional = $matches['fractional'];
|
||||
$exponent = $matches['exponent'];
|
||||
|
||||
$scale = \strlen($fractional) - $exponent;
|
||||
if ($integral === null && $fractional === null) {
|
||||
throw NumberFormatException::invalidFormat($value);
|
||||
}
|
||||
|
||||
if ($scale < 0) {
|
||||
if ($unscaledValue !== '0') {
|
||||
$unscaledValue .= \str_repeat('0', - $scale);
|
||||
if ($integral === null) {
|
||||
$integral = '0';
|
||||
}
|
||||
|
||||
if ($point !== null || $exponent !== null) {
|
||||
$fractional = ($fractional ?? '');
|
||||
$exponent = ($exponent !== null) ? (int)$exponent : 0;
|
||||
|
||||
if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) {
|
||||
throw new NumberFormatException('Exponent too large.');
|
||||
}
|
||||
$scale = 0;
|
||||
|
||||
$unscaledValue = self::cleanUp($sign, $integral . $fractional);
|
||||
|
||||
$scale = \strlen($fractional) - $exponent;
|
||||
|
||||
if ($scale < 0) {
|
||||
if ($unscaledValue !== '0') {
|
||||
$unscaledValue .= \str_repeat('0', -$scale);
|
||||
}
|
||||
$scale = 0;
|
||||
}
|
||||
|
||||
return new BigDecimal($unscaledValue, $scale);
|
||||
}
|
||||
|
||||
return new BigDecimal($unscaledValue, $scale);
|
||||
$integral = self::cleanUp($sign, $integral);
|
||||
|
||||
return new BigInteger($integral);
|
||||
}
|
||||
|
||||
$integral = self::cleanUp(($sign ?? '') . $integral);
|
||||
|
||||
return new BigInteger($integral);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely converts float to string, avoiding locale-dependent issues.
|
||||
* Overridden by subclasses to convert a BigNumber to an instance of the subclass.
|
||||
*
|
||||
* @see https://github.com/brick/math/pull/20
|
||||
* @throws MathException If the value cannot be converted.
|
||||
*
|
||||
* @psalm-pure
|
||||
* @psalm-suppress ImpureFunctionCall
|
||||
*/
|
||||
private static function floatToString(float $float) : string
|
||||
{
|
||||
$currentLocale = \setlocale(LC_NUMERIC, '0');
|
||||
\setlocale(LC_NUMERIC, 'C');
|
||||
|
||||
$result = (string) $float;
|
||||
|
||||
\setlocale(LC_NUMERIC, $currentLocale);
|
||||
|
||||
return $result;
|
||||
}
|
||||
abstract protected static function from(BigNumber $number): static;
|
||||
|
||||
/**
|
||||
* Proxy method to access BigInteger's protected constructor from sibling classes.
|
||||
@@ -169,7 +175,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
* @internal
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected function newBigInteger(string $value) : BigInteger
|
||||
final protected function newBigInteger(string $value) : BigInteger
|
||||
{
|
||||
return new BigInteger($value);
|
||||
}
|
||||
@@ -180,7 +186,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
* @internal
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected function newBigDecimal(string $value, int $scale = 0) : BigDecimal
|
||||
final protected function newBigDecimal(string $value, int $scale = 0) : BigDecimal
|
||||
{
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
@@ -191,7 +197,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
* @internal
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) : BigRational
|
||||
final protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) : BigRational
|
||||
{
|
||||
return new BigRational($numerator, $denominator, $checkDenominator);
|
||||
}
|
||||
@@ -205,11 +211,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
* @throws \InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
*
|
||||
* @psalm-suppress LessSpecificReturnStatement
|
||||
* @psalm-suppress MoreSpecificReturnType
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function min(BigNumber|int|float|string ...$values) : static
|
||||
final public static function min(BigNumber|int|float|string ...$values) : static
|
||||
{
|
||||
$min = null;
|
||||
|
||||
@@ -237,11 +241,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
* @throws \InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
*
|
||||
* @psalm-suppress LessSpecificReturnStatement
|
||||
* @psalm-suppress MoreSpecificReturnType
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function max(BigNumber|int|float|string ...$values) : static
|
||||
final public static function max(BigNumber|int|float|string ...$values) : static
|
||||
{
|
||||
$max = null;
|
||||
|
||||
@@ -271,7 +273,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function sum(BigNumber|int|float|string ...$values) : static
|
||||
final public static function sum(BigNumber|int|float|string ...$values) : static
|
||||
{
|
||||
/** @var static|null $sum */
|
||||
$sum = null;
|
||||
@@ -323,37 +325,28 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes optional leading zeros and + sign from the given number.
|
||||
* Removes optional leading zeros and applies sign.
|
||||
*
|
||||
* @param string $number The number, validated as a non-empty string of digits with optional leading sign.
|
||||
* @param string|null $sign The sign, '+' or '-', optional. Null is allowed for convenience and treated as '+'.
|
||||
* @param string $number The number, validated as a non-empty string of digits.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
private static function cleanUp(string $number) : string
|
||||
private static function cleanUp(string|null $sign, string $number) : string
|
||||
{
|
||||
$firstChar = $number[0];
|
||||
|
||||
if ($firstChar === '+' || $firstChar === '-') {
|
||||
$number = \substr($number, 1);
|
||||
}
|
||||
|
||||
$number = \ltrim($number, '0');
|
||||
|
||||
if ($number === '') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
if ($firstChar === '-') {
|
||||
return '-' . $number;
|
||||
}
|
||||
|
||||
return $number;
|
||||
return $sign === '-' ? '-' . $number : $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is equal to the given one.
|
||||
*/
|
||||
public function isEqualTo(BigNumber|int|float|string $that) : bool
|
||||
final public function isEqualTo(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) === 0;
|
||||
}
|
||||
@@ -361,7 +354,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
/**
|
||||
* Checks if this number is strictly lower than the given one.
|
||||
*/
|
||||
public function isLessThan(BigNumber|int|float|string $that) : bool
|
||||
final public function isLessThan(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) < 0;
|
||||
}
|
||||
@@ -369,7 +362,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
/**
|
||||
* Checks if this number is lower than or equal to the given one.
|
||||
*/
|
||||
public function isLessThanOrEqualTo(BigNumber|int|float|string $that) : bool
|
||||
final public function isLessThanOrEqualTo(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) <= 0;
|
||||
}
|
||||
@@ -377,7 +370,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
/**
|
||||
* Checks if this number is strictly greater than the given one.
|
||||
*/
|
||||
public function isGreaterThan(BigNumber|int|float|string $that) : bool
|
||||
final public function isGreaterThan(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) > 0;
|
||||
}
|
||||
@@ -385,7 +378,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
/**
|
||||
* Checks if this number is greater than or equal to the given one.
|
||||
*/
|
||||
public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that) : bool
|
||||
final public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that) : bool
|
||||
{
|
||||
return $this->compareTo($that) >= 0;
|
||||
}
|
||||
@@ -393,7 +386,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
/**
|
||||
* Checks if this number equals zero.
|
||||
*/
|
||||
public function isZero() : bool
|
||||
final public function isZero() : bool
|
||||
{
|
||||
return $this->getSign() === 0;
|
||||
}
|
||||
@@ -401,7 +394,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
/**
|
||||
* Checks if this number is strictly negative.
|
||||
*/
|
||||
public function isNegative() : bool
|
||||
final public function isNegative() : bool
|
||||
{
|
||||
return $this->getSign() < 0;
|
||||
}
|
||||
@@ -409,7 +402,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
/**
|
||||
* Checks if this number is negative or zero.
|
||||
*/
|
||||
public function isNegativeOrZero() : bool
|
||||
final public function isNegativeOrZero() : bool
|
||||
{
|
||||
return $this->getSign() <= 0;
|
||||
}
|
||||
@@ -417,7 +410,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
/**
|
||||
* Checks if this number is strictly positive.
|
||||
*/
|
||||
public function isPositive() : bool
|
||||
final public function isPositive() : bool
|
||||
{
|
||||
return $this->getSign() > 0;
|
||||
}
|
||||
@@ -425,7 +418,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
/**
|
||||
* Checks if this number is positive or zero.
|
||||
*/
|
||||
public function isPositiveOrZero() : bool
|
||||
final public function isPositiveOrZero() : bool
|
||||
{
|
||||
return $this->getSign() >= 0;
|
||||
}
|
||||
@@ -433,6 +426,8 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
/**
|
||||
* Returns the sign of this number.
|
||||
*
|
||||
* @psalm-return -1|0|1
|
||||
*
|
||||
* @return int -1 if the number is negative, 0 if zero, 1 if positive.
|
||||
*/
|
||||
abstract public function getSign() : int;
|
||||
@@ -440,7 +435,9 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
/**
|
||||
* Compares this number to the given one.
|
||||
*
|
||||
* @return int [-1,0,1] If `$this` is lower than, equal to, or greater than `$that`.
|
||||
* @psalm-return -1|0|1
|
||||
*
|
||||
* @return int -1 if `$this` is lower than, 0 if equal to, 1 if greater than `$that`.
|
||||
*
|
||||
* @throws MathException If the number is not valid.
|
||||
*/
|
||||
@@ -468,13 +465,13 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
/**
|
||||
* Converts this number to a BigDecimal with the given scale, using rounding if necessary.
|
||||
*
|
||||
* @param int $scale The scale of the resulting `BigDecimal`.
|
||||
* @param int $roundingMode A `RoundingMode` constant.
|
||||
* @param int $scale The scale of the resulting `BigDecimal`.
|
||||
* @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
|
||||
*
|
||||
* @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding.
|
||||
* This only applies when RoundingMode::UNNECESSARY is used.
|
||||
*/
|
||||
abstract public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal;
|
||||
abstract public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal;
|
||||
|
||||
/**
|
||||
* Returns the exact value of this number as a native integer.
|
||||
@@ -505,7 +502,7 @@ abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
*/
|
||||
abstract public function __toString() : string;
|
||||
|
||||
public function jsonSerialize() : string
|
||||
final public function jsonSerialize() : string
|
||||
{
|
||||
return $this->__toString();
|
||||
}
|
||||
|
||||
+7
-39
@@ -21,12 +21,12 @@ final class BigRational extends BigNumber
|
||||
/**
|
||||
* The numerator.
|
||||
*/
|
||||
private BigInteger $numerator;
|
||||
private readonly BigInteger $numerator;
|
||||
|
||||
/**
|
||||
* The denominator. Always strictly positive.
|
||||
*/
|
||||
private BigInteger $denominator;
|
||||
private readonly BigInteger $denominator;
|
||||
|
||||
/**
|
||||
* Protected constructor. Use a factory method to obtain an instance.
|
||||
@@ -55,15 +55,11 @@ final class BigRational extends BigNumber
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigRational of the given value.
|
||||
*
|
||||
* @throws MathException If the value cannot be converted to a BigRational.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of(BigNumber|int|float|string $value) : BigRational
|
||||
protected static function from(BigNumber $number): static
|
||||
{
|
||||
return parent::of($value)->toBigRational();
|
||||
return $number->toBigRational();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,6 +177,8 @@ final class BigRational extends BigNumber
|
||||
* Returns the quotient and remainder of the division of the numerator by the denominator.
|
||||
*
|
||||
* @return BigInteger[]
|
||||
*
|
||||
* @psalm-return array{BigInteger, BigInteger}
|
||||
*/
|
||||
public function quotientAndRemainder() : array
|
||||
{
|
||||
@@ -353,7 +351,7 @@ final class BigRational extends BigNumber
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
|
||||
}
|
||||
@@ -412,34 +410,4 @@ final class BigRational extends BigNumber
|
||||
$this->numerator = $data['numerator'];
|
||||
$this->denominator = $data['denominator'];
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required by interface Serializable and SHOULD NOT be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function serialize() : string
|
||||
{
|
||||
return $this->numerator . '/' . $this->denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only here to implement interface Serializable and cannot be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
* @psalm-suppress RedundantPropertyInitializationCheck
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function unserialize($value) : void
|
||||
{
|
||||
if (isset($this->numerator)) {
|
||||
throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
|
||||
}
|
||||
|
||||
[$numerator, $denominator] = \explode('/', $value);
|
||||
|
||||
$this->numerator = BigInteger::of($numerator);
|
||||
$this->denominator = BigInteger::of($denominator);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -9,6 +9,14 @@ namespace Brick\Math\Exception;
|
||||
*/
|
||||
class NumberFormatException extends MathException
|
||||
{
|
||||
public static function invalidFormat(string $value) : self
|
||||
{
|
||||
return new self(\sprintf(
|
||||
'The given value "%s" does not represent a valid number.',
|
||||
$value,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $char The failing character.
|
||||
*
|
||||
@@ -28,6 +36,6 @@ class NumberFormatException extends MathException
|
||||
$char = '"' . $char . '"';
|
||||
}
|
||||
|
||||
return new self(sprintf('Char %s is not a valid character in the given alphabet.', $char));
|
||||
return new self(\sprintf('Char %s is not a valid character in the given alphabet.', $char));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ abstract class Calculator
|
||||
/**
|
||||
* The maximum exponent value allowed for the pow() method.
|
||||
*/
|
||||
public const MAX_POWER = 1000000;
|
||||
public const MAX_POWER = 1_000_000;
|
||||
|
||||
/**
|
||||
* The alphabet for converting from and to base 2 to 36, lowercase.
|
||||
@@ -128,7 +128,9 @@ abstract class Calculator
|
||||
/**
|
||||
* Compares two numbers.
|
||||
*
|
||||
* @return int [-1, 0, 1] If the first number is less than, equal to, or greater than the second number.
|
||||
* @psalm-return -1|0|1
|
||||
*
|
||||
* @return int -1 if the first number is less than, 0 if equal to, 1 if greater than the second number.
|
||||
*/
|
||||
final public function cmp(string $a, string $b) : int
|
||||
{
|
||||
@@ -428,16 +430,16 @@ abstract class Calculator
|
||||
*
|
||||
* Rounding is performed when the remainder of the division is not zero.
|
||||
*
|
||||
* @param string $a The dividend.
|
||||
* @param string $b The divisor, must not be zero.
|
||||
* @param int $roundingMode The rounding mode.
|
||||
* @param string $a The dividend.
|
||||
* @param string $b The divisor, must not be zero.
|
||||
* @param RoundingMode $roundingMode The rounding mode.
|
||||
*
|
||||
* @throws \InvalidArgumentException If the rounding mode is invalid.
|
||||
* @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
|
||||
*
|
||||
* @psalm-suppress ImpureFunctionCall
|
||||
*/
|
||||
final public function divRound(string $a, string $b, int $roundingMode) : string
|
||||
final public function divRound(string $a, string $b, RoundingMode $roundingMode) : string
|
||||
{
|
||||
[$quotient, $remainder] = $this->divQR($a, $b);
|
||||
|
||||
@@ -571,27 +573,17 @@ abstract class Calculator
|
||||
$bBin = $this->twosComplement($bBin);
|
||||
}
|
||||
|
||||
switch ($operator) {
|
||||
case 'and':
|
||||
$value = $aBin & $bBin;
|
||||
$negative = ($aNeg and $bNeg);
|
||||
break;
|
||||
$value = match ($operator) {
|
||||
'and' => $aBin & $bBin,
|
||||
'or' => $aBin | $bBin,
|
||||
'xor' => $aBin ^ $bBin,
|
||||
};
|
||||
|
||||
case 'or':
|
||||
$value = $aBin | $bBin;
|
||||
$negative = ($aNeg or $bNeg);
|
||||
break;
|
||||
|
||||
case 'xor':
|
||||
$value = $aBin ^ $bBin;
|
||||
$negative = ($aNeg xor $bNeg);
|
||||
break;
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid bitwise operator.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
$negative = match ($operator) {
|
||||
'and' => $aNeg and $bNeg,
|
||||
'or' => $aNeg or $bNeg,
|
||||
'xor' => $aNeg xor $bNeg,
|
||||
};
|
||||
|
||||
if ($negative) {
|
||||
$value = $this->twosComplement($value);
|
||||
|
||||
-10
@@ -35,10 +35,6 @@ class BcMathCalculator extends Calculator
|
||||
return \bcdiv($a, $b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress InvalidNullableReturnType
|
||||
* @psalm-suppress NullableReturnStatement
|
||||
*/
|
||||
public function divR(string $a, string $b) : string
|
||||
{
|
||||
return \bcmod($a, $b, 0);
|
||||
@@ -49,8 +45,6 @@ class BcMathCalculator extends Calculator
|
||||
$q = \bcdiv($a, $b, 0);
|
||||
$r = \bcmod($a, $b, 0);
|
||||
|
||||
assert($r !== null);
|
||||
|
||||
return [$q, $r];
|
||||
}
|
||||
|
||||
@@ -64,10 +58,6 @@ class BcMathCalculator extends Calculator
|
||||
return \bcpowmod($base, $exp, $mod, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress InvalidNullableReturnType
|
||||
* @psalm-suppress NullableReturnStatement
|
||||
*/
|
||||
public function sqrt(string $n) : string
|
||||
{
|
||||
return \bcsqrt($n, 0);
|
||||
|
||||
+9
-18
@@ -23,25 +23,18 @@ class NativeCalculator extends Calculator
|
||||
* Example: 32-bit: max number 1,999,999,999 (9 digits + carry)
|
||||
* 64-bit: max number 1,999,999,999,999,999,999 (18 digits + carry)
|
||||
*/
|
||||
private int $maxDigits;
|
||||
private readonly int $maxDigits;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
switch (PHP_INT_SIZE) {
|
||||
case 4:
|
||||
$this->maxDigits = 9;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
$this->maxDigits = 18;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.');
|
||||
}
|
||||
$this->maxDigits = match (PHP_INT_SIZE) {
|
||||
4 => 9,
|
||||
8 => 18,
|
||||
default => throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.')
|
||||
};
|
||||
}
|
||||
|
||||
public function add(string $a, string $b) : string
|
||||
@@ -161,10 +154,8 @@ class NativeCalculator extends Calculator
|
||||
if (is_int($nb)) {
|
||||
// the only division that may overflow is PHP_INT_MIN / -1,
|
||||
// which cannot happen here as we've already handled a divisor of -1 above.
|
||||
$q = intdiv($na, $nb);
|
||||
$r = $na % $nb;
|
||||
$q = ($na - $r) / $nb;
|
||||
|
||||
assert(is_int($q));
|
||||
|
||||
return [
|
||||
(string) $q,
|
||||
@@ -536,7 +527,7 @@ class NativeCalculator extends Calculator
|
||||
/**
|
||||
* Compares two non-signed large numbers.
|
||||
*
|
||||
* @return int [-1, 0, 1]
|
||||
* @psalm-return -1|0|1
|
||||
*/
|
||||
private function doCmp(string $a, string $b) : int
|
||||
{
|
||||
@@ -549,7 +540,7 @@ class NativeCalculator extends Calculator
|
||||
return $cmp;
|
||||
}
|
||||
|
||||
return \strcmp($a, $b) <=> 0; // enforce [-1, 0, 1]
|
||||
return \strcmp($a, $b) <=> 0; // enforce -1|0|1
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+11
-20
@@ -13,24 +13,15 @@ namespace Brick\Math;
|
||||
* regardless the digits' contribution to the value of the number. In other words, considered
|
||||
* as a numerical value, the discarded fraction could have an absolute value greater than one.
|
||||
*/
|
||||
final class RoundingMode
|
||||
enum RoundingMode
|
||||
{
|
||||
/**
|
||||
* Private constructor. This class is not instantiable.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the requested operation has an exact result, hence no rounding is necessary.
|
||||
*
|
||||
* If this rounding mode is specified on an operation that yields a result that
|
||||
* cannot be represented at the requested scale, a RoundingNecessaryException is thrown.
|
||||
*/
|
||||
public const UNNECESSARY = 0;
|
||||
case UNNECESSARY;
|
||||
|
||||
/**
|
||||
* Rounds away from zero.
|
||||
@@ -38,7 +29,7 @@ final class RoundingMode
|
||||
* Always increments the digit prior to a nonzero discarded fraction.
|
||||
* Note that this rounding mode never decreases the magnitude of the calculated value.
|
||||
*/
|
||||
public const UP = 1;
|
||||
case UP;
|
||||
|
||||
/**
|
||||
* Rounds towards zero.
|
||||
@@ -46,7 +37,7 @@ final class RoundingMode
|
||||
* Never increments the digit prior to a discarded fraction (i.e., truncates).
|
||||
* Note that this rounding mode never increases the magnitude of the calculated value.
|
||||
*/
|
||||
public const DOWN = 2;
|
||||
case DOWN;
|
||||
|
||||
/**
|
||||
* Rounds towards positive infinity.
|
||||
@@ -54,7 +45,7 @@ final class RoundingMode
|
||||
* If the result is positive, behaves as for UP; if negative, behaves as for DOWN.
|
||||
* Note that this rounding mode never decreases the calculated value.
|
||||
*/
|
||||
public const CEILING = 3;
|
||||
case CEILING;
|
||||
|
||||
/**
|
||||
* Rounds towards negative infinity.
|
||||
@@ -62,7 +53,7 @@ final class RoundingMode
|
||||
* If the result is positive, behave as for DOWN; if negative, behave as for UP.
|
||||
* Note that this rounding mode never increases the calculated value.
|
||||
*/
|
||||
public const FLOOR = 4;
|
||||
case FLOOR;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
|
||||
@@ -70,28 +61,28 @@ final class RoundingMode
|
||||
* Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves as for DOWN.
|
||||
* Note that this is the rounding mode commonly taught at school.
|
||||
*/
|
||||
public const HALF_UP = 5;
|
||||
case HALF_UP;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
|
||||
*
|
||||
* Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN.
|
||||
*/
|
||||
public const HALF_DOWN = 6;
|
||||
case HALF_DOWN;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity.
|
||||
*
|
||||
* If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN.
|
||||
*/
|
||||
public const HALF_CEILING = 7;
|
||||
case HALF_CEILING;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity.
|
||||
*
|
||||
* If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP.
|
||||
*/
|
||||
public const HALF_FLOOR = 8;
|
||||
case HALF_FLOOR;
|
||||
|
||||
/**
|
||||
* Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
|
||||
@@ -103,5 +94,5 @@ final class RoundingMode
|
||||
* cumulative error when applied repeatedly over a sequence of calculations.
|
||||
* It is sometimes known as "Banker's rounding", and is chiefly used in the USA.
|
||||
*/
|
||||
public const HALF_EVEN = 9;
|
||||
case HALF_EVEN;
|
||||
}
|
||||
|
||||
@@ -322,6 +322,7 @@ class InstalledVersions
|
||||
}
|
||||
|
||||
$installed = array();
|
||||
$copiedLocalDir = false;
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
@@ -330,9 +331,11 @@ class InstalledVersions
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require $vendorDir.'/composer/installed.php';
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
self::$installedByVendor[$vendorDir] = $required;
|
||||
$installed[] = $required;
|
||||
if (strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $required;
|
||||
$copiedLocalDir = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -350,7 +353,7 @@ class InstalledVersions
|
||||
}
|
||||
}
|
||||
|
||||
if (self::$installed !== array()) {
|
||||
if (self::$installed !== array() && !$copiedLocalDir) {
|
||||
$installed[] = self::$installed;
|
||||
}
|
||||
|
||||
|
||||
+719
-418
File diff suppressed because it is too large
Load Diff
@@ -6,15 +6,14 @@ $vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
|
||||
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
|
||||
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
|
||||
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
|
||||
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
@@ -24,6 +23,7 @@ return array(
|
||||
'47e1160838b5e5a10346ac4084b58c23' => $vendorDir . '/laravel/prompts/src/helpers.php',
|
||||
'6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php',
|
||||
'35a6ad97d21e794e7e22a17d806652e4' => $vendorDir . '/nunomaduro/termwind/src/Functions.php',
|
||||
'9b38cf48e83f5d8f60375221cd213eee' => $vendorDir . '/phpstan/phpstan/bootstrap.php',
|
||||
'801c31d8ed748cfa537fa45402288c95' => $vendorDir . '/psy/psysh/src/functions.php',
|
||||
'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
|
||||
'e23faeee409e941dc9b4c80386209c39' => $vendorDir . '/laracasts/flash/src/Laracasts/Flash/functions.php',
|
||||
@@ -37,7 +37,6 @@ return array(
|
||||
'c72349b1fe8d0deeedd3a52e8aa814d8' => $vendorDir . '/mockery/mockery/library/helpers.php',
|
||||
'ce9671a430e4846b44e1c68c7611f9f5' => $vendorDir . '/mockery/mockery/library/Mockery.php',
|
||||
'9f394da3192a168c4633675768d80428' => $vendorDir . '/nwidart/laravel-modules/src/helpers.php',
|
||||
'9b38cf48e83f5d8f60375221cd213eee' => $vendorDir . '/phpstan/phpstan/bootstrap.php',
|
||||
'ec07570ca5a812141189b1fa81503674' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert/Functions.php',
|
||||
'377b22b161c09ed6e5152de788ca020a' => $vendorDir . '/spatie/laravel-permission/src/helpers.php',
|
||||
'646961a8eab48144f6c03fc7c3185753' => $baseDir . '/app/Http/Helpers/Functions.php',
|
||||
|
||||
+9
-3
@@ -16,7 +16,6 @@ return array(
|
||||
'Symfony\\Polyfill\\Uuid\\' => array($vendorDir . '/symfony/polyfill-uuid'),
|
||||
'Symfony\\Polyfill\\Php83\\' => array($vendorDir . '/symfony/polyfill-php83'),
|
||||
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
|
||||
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
|
||||
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
|
||||
'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
|
||||
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
|
||||
@@ -40,8 +39,10 @@ return array(
|
||||
'Symfony\\Component\\ErrorHandler\\' => array($vendorDir . '/symfony/error-handler'),
|
||||
'Symfony\\Component\\CssSelector\\' => array($vendorDir . '/symfony/css-selector'),
|
||||
'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
|
||||
'Svg\\' => array($vendorDir . '/phenx/php-svg-lib/src/Svg'),
|
||||
'Streamline\\' => array($baseDir . '/app'),
|
||||
'Spatie\\Permission\\' => array($vendorDir . '/spatie/laravel-permission/src'),
|
||||
'Sabberworm\\CSS\\' => array($vendorDir . '/sabberworm/php-css-parser/src'),
|
||||
'Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'),
|
||||
'Ramsey\\Collection\\' => array($vendorDir . '/ramsey/collection/src'),
|
||||
'Psy\\' => array($vendorDir . '/psy/psysh/src'),
|
||||
@@ -55,11 +56,13 @@ return array(
|
||||
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
|
||||
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
|
||||
'PhpOption\\' => array($vendorDir . '/phpoption/phpoption/src/PhpOption'),
|
||||
'PhpMyAdmin\\SqlParser\\' => array($vendorDir . '/phpmyadmin/sql-parser/src'),
|
||||
'OwenIt\\Auditing\\' => array($vendorDir . '/owen-it/laravel-auditing/src'),
|
||||
'Nwidart\\Modules\\' => array($vendorDir . '/nwidart/laravel-modules/src'),
|
||||
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
|
||||
'Modules\\' => array($baseDir . '/Modules'),
|
||||
'Mockery\\' => array($vendorDir . '/mockery/mockery/library/Mockery'),
|
||||
'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'),
|
||||
'League\\MimeTypeDetection\\' => array($vendorDir . '/league/mime-type-detection/src'),
|
||||
'League\\Flysystem\\Local\\' => array($vendorDir . '/league/flysystem-local'),
|
||||
'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
|
||||
@@ -69,6 +72,7 @@ return array(
|
||||
'Laravel\\Tinker\\' => array($vendorDir . '/laravel/tinker/src'),
|
||||
'Laravel\\SerializableClosure\\' => array($vendorDir . '/laravel/serializable-closure/src'),
|
||||
'Laravel\\Prompts\\' => array($vendorDir . '/laravel/prompts/src'),
|
||||
'Larastan\\Larastan\\' => array($vendorDir . '/larastan/larastan/src'),
|
||||
'Knp\\Snappy\\' => array($vendorDir . '/knplabs/knp-snappy/src/Knp/Snappy'),
|
||||
'Illuminate\\Support\\' => array($vendorDir . '/laravel/framework/src/Illuminate/Macroable', $vendorDir . '/laravel/framework/src/Illuminate/Collections', $vendorDir . '/laravel/framework/src/Illuminate/Conditionable'),
|
||||
'Illuminate\\Foundation\\Auth\\' => array($vendorDir . '/laravel/ui/auth-backend'),
|
||||
@@ -80,11 +84,13 @@ return array(
|
||||
'GrahamCampbell\\ResultType\\' => array($vendorDir . '/graham-campbell/result-type/src'),
|
||||
'Fx3costa\\LaravelChartJs\\' => array($vendorDir . '/fx3costa/laravelchartjs/src'),
|
||||
'Fruitcake\\Cors\\' => array($vendorDir . '/fruitcake/php-cors/src'),
|
||||
'FontLib\\' => array($vendorDir . '/phenx/php-font-lib/src/FontLib'),
|
||||
'Faker\\' => array($vendorDir . '/fakerphp/faker/src/Faker'),
|
||||
'Egulias\\EmailValidator\\' => array($vendorDir . '/egulias/email-validator/src'),
|
||||
'Dotenv\\' => array($vendorDir . '/vlucas/phpdotenv/src'),
|
||||
'Dompdf\\' => array($vendorDir . '/dompdf/dompdf/src'),
|
||||
'Doctrine\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Inflector'),
|
||||
'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/lib/Doctrine/Deprecations'),
|
||||
'Doctrine\\Deprecations\\' => array($vendorDir . '/doctrine/deprecations/src'),
|
||||
'Doctrine\\DBAL\\' => array($vendorDir . '/doctrine/dbal/src'),
|
||||
'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/src'),
|
||||
'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache'),
|
||||
@@ -97,6 +103,6 @@ return array(
|
||||
'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'),
|
||||
'Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
|
||||
'Barryvdh\\Snappy\\' => array($vendorDir . '/barryvdh/laravel-snappy/src'),
|
||||
'AfricasTalking\\SDK\\Tests\\' => array($vendorDir . '/africastalking/africastalking/tests'),
|
||||
'Barryvdh\\DomPDF\\' => array($vendorDir . '/barryvdh/laravel-dompdf/src'),
|
||||
'AfricasTalking\\SDK\\' => array($vendorDir . '/africastalking/africastalking/src'),
|
||||
);
|
||||
|
||||
+5
-5
@@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit379a36e429894b61b55afc3b84fa116a
|
||||
class ComposerAutoloaderInit69a41de4ce3c76c7865a7de0eec12ccc
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
@@ -24,16 +24,16 @@ class ComposerAutoloaderInit379a36e429894b61b55afc3b84fa116a
|
||||
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit379a36e429894b61b55afc3b84fa116a', 'loadClassLoader'), true, true);
|
||||
spl_autoload_register(array('ComposerAutoloaderInit69a41de4ce3c76c7865a7de0eec12ccc', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit379a36e429894b61b55afc3b84fa116a', 'loadClassLoader'));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit69a41de4ce3c76c7865a7de0eec12ccc', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit379a36e429894b61b55afc3b84fa116a::getInitializer($loader));
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit69a41de4ce3c76c7865a7de0eec12ccc::getInitializer($loader));
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit379a36e429894b61b55afc3b84fa116a::$files;
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit69a41de4ce3c76c7865a7de0eec12ccc::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
+767
-437
File diff suppressed because it is too large
Load Diff
+1404
-908
File diff suppressed because it is too large
Load Diff
+355
-292
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [3.0.3] - 2024-07-08
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed PHP 8.4 deprecation notices (#47)
|
||||
|
||||
## [3.0.2] - 2022-10-27
|
||||
|
||||
### Fixed
|
||||
@@ -57,7 +63,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
**Initial release!**
|
||||
|
||||
[Unreleased]: https://github.com/dflydev/dflydev-dot-access-data/compare/v3.0.2...main
|
||||
[Unreleased]: https://github.com/dflydev/dflydev-dot-access-data/compare/v3.0.3...main
|
||||
[3.0.3]: https://github.com/dflydev/dflydev-dot-access-data/compare/v3.0.2...v3.0.3
|
||||
[3.0.2]: https://github.com/dflydev/dflydev-dot-access-data/compare/v3.0.1...v3.0.2
|
||||
[3.0.1]: https://github.com/dflydev/dflydev-dot-access-data/compare/v3.0.0...v3.0.1
|
||||
[3.0.0]: https://github.com/dflydev/dflydev-dot-access-data/compare/v2.0.0...v3.0.0
|
||||
|
||||
Vendored
+1
-1
@@ -23,7 +23,7 @@ class MissingPathException extends DataException
|
||||
/** @var string */
|
||||
protected $path;
|
||||
|
||||
public function __construct(string $path, string $message = '', int $code = 0, Throwable $previous = null)
|
||||
public function __construct(string $path, string $message = '', int $code = 0, ?Throwable $previous = null)
|
||||
{
|
||||
$this->path = $path;
|
||||
|
||||
|
||||
+20
-28
@@ -1,11 +1,11 @@
|
||||
# Doctrine DBAL
|
||||
|
||||
| [5.0-dev][5.0] | [4.1-dev][4.1] | [4.0][4.0] | [3.9-dev][3.9] | [3.8][3.8] |
|
||||
|:---------------------------------------------------:|:---------------------------------------------------:|:---------------------------------------------------:|:---------------------------------------------------:|:---------------------------------------------------:|
|
||||
| [![GitHub Actions][GA 5.0 image]][GA 5.0] | [![GitHub Actions][GA 4.1 image]][GA 4.1] | [![GitHub Actions][GA 4.0 image]][GA 4.0] | [![GitHub Actions][GA 3.9 image]][GA 3.9] | [![GitHub Actions][GA 3.8 image]][GA 3.8] |
|
||||
| [![AppVeyor][AppVeyor 5.0 image]][AppVeyor 5.0] | [![AppVeyor][AppVeyor 4.1 image]][AppVeyor 4.1] | [![AppVeyor][AppVeyor 4.0 image]][AppVeyor 4.0] | [![AppVeyor][AppVeyor 3.9 image]][AppVeyor 3.9] | [![AppVeyor][AppVeyor 3.8 image]][AppVeyor 3.8] |
|
||||
| [![Code Coverage][Coverage 5.0 image]][CodeCov 5.0] | [![Code Coverage][Coverage 4.1 image]][CodeCov 4.1] | [![Code Coverage][Coverage 4.0 image]][CodeCov 4.0] | [![Code Coverage][Coverage 3.9 image]][CodeCov 3.9] | [![Code Coverage][Coverage 3.8 image]][CodeCov 3.8] |
|
||||
| N/A | N/A | [![Type Coverage][TypeCov image]][TypeCov] | N/A | |
|
||||
| [5.0-dev][5.0] | [4.3-dev][4.3] | [4.2][4.2] | [3.9][3.9] |
|
||||
|:---------------------------------------------------:|:---------------------------------------------------:|:---------------------------------------------------:|:---------------------------------------------------:|
|
||||
| [![GitHub Actions][GA 5.0 image]][GA 5.0] | [![GitHub Actions][GA 4.3 image]][GA 4.3] | [![GitHub Actions][GA 4.2 image]][GA 4.2] | [![GitHub Actions][GA 3.9 image]][GA 3.9] |
|
||||
| [![AppVeyor][AppVeyor 5.0 image]][AppVeyor 5.0] | [![AppVeyor][AppVeyor 4.3 image]][AppVeyor 4.3] | [![AppVeyor][AppVeyor 4.2 image]][AppVeyor 4.2] | [![AppVeyor][AppVeyor 3.9 image]][AppVeyor 3.9] |
|
||||
| [![Code Coverage][Coverage 5.0 image]][CodeCov 5.0] | [![Code Coverage][Coverage 4.3 image]][CodeCov 4.3] | [![Code Coverage][Coverage 4.2 image]][CodeCov 4.2] | [![Code Coverage][Coverage 3.9 image]][CodeCov 3.9] |
|
||||
| N/A | N/A | [![Type Coverage][TypeCov image]][TypeCov] | N/A |
|
||||
|
||||
Powerful ***D***ata***B***ase ***A***bstraction ***L***ayer with many features for database schema introspection and schema management.
|
||||
|
||||
@@ -23,21 +23,21 @@ Powerful ***D***ata***B***ase ***A***bstraction ***L***ayer with many features f
|
||||
[GA 5.0]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A5.0.x
|
||||
[GA 5.0 image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg?branch=5.0.x
|
||||
|
||||
[Coverage 4.1 image]: https://codecov.io/gh/doctrine/dbal/branch/4.1.x/graph/badge.svg
|
||||
[4.1]: https://github.com/doctrine/dbal/tree/4.1.x
|
||||
[CodeCov 4.1]: https://codecov.io/gh/doctrine/dbal/branch/4.1.x
|
||||
[AppVeyor 4.1]: https://ci.appveyor.com/project/doctrine/dbal/branch/4.1.x
|
||||
[AppVeyor 4.1 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/4.1.x?svg=true
|
||||
[GA 4.1]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A4.1.x
|
||||
[GA 4.1 image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg?branch=4.1.x
|
||||
[Coverage 4.3 image]: https://codecov.io/gh/doctrine/dbal/branch/4.3.x/graph/badge.svg
|
||||
[4.3]: https://github.com/doctrine/dbal/tree/4.3.x
|
||||
[CodeCov 4.3]: https://codecov.io/gh/doctrine/dbal/branch/4.3.x
|
||||
[AppVeyor 4.3]: https://ci.appveyor.com/project/doctrine/dbal/branch/4.3.x
|
||||
[AppVeyor 4.3 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/4.3.x?svg=true
|
||||
[GA 4.3]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A4.3.x
|
||||
[GA 4.3 image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg?branch=4.3.x
|
||||
|
||||
[Coverage 4.0 image]: https://codecov.io/gh/doctrine/dbal/branch/4.0.x/graph/badge.svg
|
||||
[4.0]: https://github.com/doctrine/dbal/tree/4.0.x
|
||||
[CodeCov 4.0]: https://codecov.io/gh/doctrine/dbal/branch/4.0.x
|
||||
[AppVeyor 4.0]: https://ci.appveyor.com/project/doctrine/dbal/branch/4.0.x
|
||||
[AppVeyor 4.0 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/4.0.x?svg=true
|
||||
[GA 4.0]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A4.0.x
|
||||
[GA 4.0 image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg?branch=4.0.x
|
||||
[Coverage 4.2 image]: https://codecov.io/gh/doctrine/dbal/branch/4.2.x/graph/badge.svg
|
||||
[4.2]: https://github.com/doctrine/dbal/tree/4.2.x
|
||||
[CodeCov 4.2]: https://codecov.io/gh/doctrine/dbal/branch/4.2.x
|
||||
[AppVeyor 4.2]: https://ci.appveyor.com/project/doctrine/dbal/branch/4.2.x
|
||||
[AppVeyor 4.2 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/4.2.x?svg=true
|
||||
[GA 4.2]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A4.2.x
|
||||
[GA 4.2 image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg?branch=4.2.x
|
||||
[TypeCov]: https://shepherd.dev/github/doctrine/dbal
|
||||
[TypeCov image]: https://shepherd.dev/github/doctrine/dbal/coverage.svg
|
||||
|
||||
@@ -48,11 +48,3 @@ Powerful ***D***ata***B***ase ***A***bstraction ***L***ayer with many features f
|
||||
[AppVeyor 3.9 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/3.9.x?svg=true
|
||||
[GA 3.9]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A3.9.x
|
||||
[GA 3.9 image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg?branch=3.9.x
|
||||
|
||||
[Coverage 3.8 image]: https://codecov.io/gh/doctrine/dbal/branch/3.8.x/graph/badge.svg
|
||||
[3.8]: https://github.com/doctrine/dbal/tree/3.8.x
|
||||
[CodeCov 3.8]: https://codecov.io/gh/doctrine/dbal/branch/3.8.x
|
||||
[AppVeyor 3.8]: https://ci.appveyor.com/project/doctrine/dbal/branch/3.8.x
|
||||
[AppVeyor 3.8 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/3.8.x?svg=true
|
||||
[GA 3.8]: https://github.com/doctrine/dbal/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A3.8.x
|
||||
[GA 3.8 image]: https://github.com/doctrine/dbal/workflows/Continuous%20Integration/badge.svg?branch=3.8.x
|
||||
|
||||
@@ -43,12 +43,12 @@
|
||||
"doctrine/coding-standard": "12.0.0",
|
||||
"fig/log-test": "^1",
|
||||
"jetbrains/phpstorm-stubs": "2023.1",
|
||||
"phpstan/phpstan": "1.10.57",
|
||||
"phpstan/phpstan-strict-rules": "^1.5",
|
||||
"phpunit/phpunit": "9.6.16",
|
||||
"phpstan/phpstan": "1.12.6",
|
||||
"phpstan/phpstan-strict-rules": "^1.6",
|
||||
"phpunit/phpunit": "9.6.20",
|
||||
"psalm/plugin-phpunit": "0.18.4",
|
||||
"slevomat/coding-standard": "8.13.1",
|
||||
"squizlabs/php_codesniffer": "3.8.1",
|
||||
"squizlabs/php_codesniffer": "3.10.2",
|
||||
"symfony/cache": "^5.4|^6.0|^7.0",
|
||||
"symfony/console": "^4.4|^5.4|^6.0|^7.0",
|
||||
"vimeo/psalm": "4.30.0"
|
||||
|
||||
@@ -1317,10 +1317,6 @@ class Connection
|
||||
throw ConnectionException::mayNotAlterNestedTransactionWithSavepointsInTransaction();
|
||||
}
|
||||
|
||||
if (! $this->getDatabasePlatform()->supportsSavepoints()) {
|
||||
throw ConnectionException::savepointsNotSupported();
|
||||
}
|
||||
|
||||
$this->nestTransactionsWithSavepoints = (bool) $nestTransactionsWithSavepoints;
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -101,6 +101,7 @@ final class ExceptionConverter implements ExceptionConverterInterface
|
||||
return new ConnectionException($exception, $query);
|
||||
|
||||
case 2006:
|
||||
case 4031:
|
||||
return new ConnectionLost($exception, $query);
|
||||
|
||||
case 1048:
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ abstract class AbstractDB2Driver implements VersionAwarePlatformDriver
|
||||
'/^(?:[^\s]+\s)?(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)/i',
|
||||
$versionString,
|
||||
$versionParts,
|
||||
) === 0
|
||||
) !== 1
|
||||
) {
|
||||
throw DBALException::invalidPlatformVersionSpecified(
|
||||
$versionString,
|
||||
|
||||
+24
-2
@@ -8,12 +8,14 @@ use Doctrine\DBAL\Driver\API\MySQL;
|
||||
use Doctrine\DBAL\Exception;
|
||||
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Platforms\MariaDb1010Platform;
|
||||
use Doctrine\DBAL\Platforms\MariaDb1027Platform;
|
||||
use Doctrine\DBAL\Platforms\MariaDb1043Platform;
|
||||
use Doctrine\DBAL\Platforms\MariaDb1052Platform;
|
||||
use Doctrine\DBAL\Platforms\MariaDb1060Platform;
|
||||
use Doctrine\DBAL\Platforms\MySQL57Platform;
|
||||
use Doctrine\DBAL\Platforms\MySQL80Platform;
|
||||
use Doctrine\DBAL\Platforms\MySQL84Platform;
|
||||
use Doctrine\DBAL\Platforms\MySQLPlatform;
|
||||
use Doctrine\DBAL\Schema\MySQLSchemaManager;
|
||||
use Doctrine\DBAL\VersionAwarePlatformDriver;
|
||||
@@ -40,6 +42,10 @@ abstract class AbstractMySQLDriver implements VersionAwarePlatformDriver
|
||||
|
||||
if ($mariadb) {
|
||||
$mariaDbVersion = $this->getMariaDbMysqlVersionNumber($version);
|
||||
if (version_compare($mariaDbVersion, '10.10.0', '>=')) {
|
||||
return new MariaDb1010Platform();
|
||||
}
|
||||
|
||||
if (version_compare($mariaDbVersion, '10.6.0', '>=')) {
|
||||
return new MariaDb1060Platform();
|
||||
}
|
||||
@@ -64,6 +70,20 @@ abstract class AbstractMySQLDriver implements VersionAwarePlatformDriver
|
||||
}
|
||||
} else {
|
||||
$oracleMysqlVersion = $this->getOracleMysqlVersionNumber($version);
|
||||
|
||||
if (version_compare($oracleMysqlVersion, '8.4.0', '>=')) {
|
||||
if (! version_compare($version, '8.4.0', '>=')) {
|
||||
Deprecation::trigger(
|
||||
'doctrine/orm',
|
||||
'https://github.com/doctrine/dbal/pull/5779',
|
||||
'Version detection logic for MySQL will change in DBAL 4. '
|
||||
. 'Please specify the version as the server reports it, e.g. "8.4.0" instead of "8.4".',
|
||||
);
|
||||
}
|
||||
|
||||
return new MySQL84Platform();
|
||||
}
|
||||
|
||||
if (version_compare($oracleMysqlVersion, '8', '>=')) {
|
||||
if (! version_compare($version, '8.0.0', '>=')) {
|
||||
Deprecation::trigger(
|
||||
@@ -116,7 +136,7 @@ abstract class AbstractMySQLDriver implements VersionAwarePlatformDriver
|
||||
'/^(?P<major>\d+)(?:\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?)?/',
|
||||
$versionString,
|
||||
$versionParts,
|
||||
) === 0
|
||||
) !== 1
|
||||
) {
|
||||
throw Exception::invalidPlatformVersionSpecified(
|
||||
$versionString,
|
||||
@@ -130,6 +150,8 @@ abstract class AbstractMySQLDriver implements VersionAwarePlatformDriver
|
||||
|
||||
if ($majorVersion === '5' && $minorVersion === '7') {
|
||||
$patchVersion ??= '9';
|
||||
} else {
|
||||
$patchVersion ??= '0';
|
||||
}
|
||||
|
||||
return $majorVersion . '.' . $minorVersion . '.' . $patchVersion;
|
||||
@@ -160,7 +182,7 @@ abstract class AbstractMySQLDriver implements VersionAwarePlatformDriver
|
||||
'/^(?:5\.5\.5-)?(mariadb-)?(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)/i',
|
||||
$versionString,
|
||||
$versionParts,
|
||||
) === 0
|
||||
) !== 1
|
||||
) {
|
||||
throw Exception::invalidPlatformVersionSpecified(
|
||||
$versionString,
|
||||
|
||||
+6
-1
@@ -8,6 +8,7 @@ use Doctrine\DBAL\Driver\API\PostgreSQL;
|
||||
use Doctrine\DBAL\Exception;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Platforms\PostgreSQL100Platform;
|
||||
use Doctrine\DBAL\Platforms\PostgreSQL120Platform;
|
||||
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
|
||||
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
|
||||
use Doctrine\DBAL\Schema\PostgreSQLSchemaManager;
|
||||
@@ -28,7 +29,7 @@ abstract class AbstractPostgreSQLDriver implements VersionAwarePlatformDriver
|
||||
*/
|
||||
public function createDatabasePlatformForVersion($version)
|
||||
{
|
||||
if (preg_match('/^(?P<major>\d+)(?:\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?)?/', $version, $versionParts) === 0) {
|
||||
if (preg_match('/^(?P<major>\d+)(?:\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?)?/', $version, $versionParts) !== 1) {
|
||||
throw Exception::invalidPlatformVersionSpecified(
|
||||
$version,
|
||||
'<major_version>.<minor_version>.<patch_version>',
|
||||
@@ -40,6 +41,10 @@ abstract class AbstractPostgreSQLDriver implements VersionAwarePlatformDriver
|
||||
$patchVersion = $versionParts['patch'] ?? 0;
|
||||
$version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion;
|
||||
|
||||
if (version_compare($version, '12.0', '>=')) {
|
||||
return new PostgreSQL120Platform();
|
||||
}
|
||||
|
||||
if (version_compare($version, '10.0', '>=')) {
|
||||
return new PostgreSQL100Platform();
|
||||
}
|
||||
|
||||
Vendored
-1
@@ -26,7 +26,6 @@ class InitializeSession implements Middleware
|
||||
'ALTER SESSION SET'
|
||||
. " NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'"
|
||||
. " NLS_TIME_FORMAT = 'HH24:MI:SS'"
|
||||
. " NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'"
|
||||
. " NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS'"
|
||||
. " NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS TZH:TZM'"
|
||||
. " NLS_NUMERIC_CHARACTERS = '.,'",
|
||||
|
||||
@@ -126,6 +126,10 @@ final class Driver extends AbstractPostgreSQLDriver
|
||||
$dsn .= 'application_name=' . $params['application_name'] . ';';
|
||||
}
|
||||
|
||||
if (isset($params['gssencmode'])) {
|
||||
$dsn .= 'gssencmode=' . $params['gssencmode'] . ';';
|
||||
}
|
||||
|
||||
return $dsn;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ final class Driver extends AbstractPostgreSQLDriver
|
||||
'user' => $params['user'] ?? null,
|
||||
'password' => $params['password'] ?? null,
|
||||
'sslmode' => $params['sslmode'] ?? null,
|
||||
'gssencmode' => $params['gssencmode'] ?? null,
|
||||
],
|
||||
static fn ($value) => $value !== '' && $value !== null,
|
||||
);
|
||||
|
||||
+26
@@ -1468,4 +1468,30 @@ SQL
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function fetchTableOptionsByTable(bool $includeTableName): string
|
||||
{
|
||||
$sql = <<<'SQL'
|
||||
SELECT t.TABLE_NAME,
|
||||
t.ENGINE,
|
||||
t.AUTO_INCREMENT,
|
||||
t.TABLE_COMMENT,
|
||||
t.CREATE_OPTIONS,
|
||||
t.TABLE_COLLATION,
|
||||
ccsa.CHARACTER_SET_NAME
|
||||
FROM information_schema.TABLES t
|
||||
INNER JOIN information_schema.COLLATION_CHARACTER_SET_APPLICABILITY ccsa
|
||||
ON ccsa.COLLATION_NAME = t.TABLE_COLLATION
|
||||
SQL;
|
||||
|
||||
$conditions = ['t.TABLE_SCHEMA = ?'];
|
||||
|
||||
if ($includeTableName) {
|
||||
$conditions[] = 't.TABLE_NAME = ?';
|
||||
}
|
||||
|
||||
$conditions[] = "t.TABLE_TYPE = 'BASE TABLE'";
|
||||
|
||||
return $sql . ' WHERE ' . implode(' AND ', $conditions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +213,7 @@ abstract class AbstractPlatform
|
||||
|
||||
foreach (Type::getTypesMap() as $typeName => $className) {
|
||||
foreach (Type::getType($typeName)->getMappedDatabaseTypes($this) as $dbType) {
|
||||
$dbType = strtolower($dbType);
|
||||
$this->doctrineTypeMapping[$dbType] = $typeName;
|
||||
}
|
||||
}
|
||||
@@ -4692,6 +4693,11 @@ abstract class AbstractPlatform
|
||||
return false;
|
||||
}
|
||||
|
||||
// If disableTypeComments is true, we do not need to check types, all comparison is already done above
|
||||
if ($this->disableTypeComments) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $column1->getType() === $column2->getType();
|
||||
}
|
||||
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\DBAL\Platforms\Keywords;
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
|
||||
use function array_diff;
|
||||
use function array_merge;
|
||||
|
||||
/**
|
||||
* MySQL 8.4 reserved keywords list.
|
||||
*/
|
||||
class MySQL84Keywords extends MySQL80Keywords
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
Deprecation::triggerIfCalledFromOutside(
|
||||
'doctrine/dbal',
|
||||
'https://github.com/doctrine/dbal/pull/5433',
|
||||
'MySQL84Keywords::getName() is deprecated.',
|
||||
);
|
||||
|
||||
return 'MySQL84';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @link https://dev.mysql.com/doc/refman/8.4/en/keywords.html
|
||||
*/
|
||||
protected function getKeywords()
|
||||
{
|
||||
$keywords = parent::getKeywords();
|
||||
|
||||
// Removed Keywords and Reserved Words
|
||||
$keywords = array_diff($keywords, [
|
||||
'MASTER_BIND',
|
||||
'MASTER_SSL_VERIFY_SERVER_CERT',
|
||||
]);
|
||||
|
||||
// New Keywords and Reserved Words
|
||||
$keywords = array_merge($keywords, [
|
||||
'AUTO',
|
||||
'BERNOULLI',
|
||||
'GTIDS',
|
||||
'LOG',
|
||||
'MANUAL',
|
||||
'PARALLEL',
|
||||
'PARSE_TREE',
|
||||
'QUALIFY',
|
||||
'S3',
|
||||
'TABLESAMPLE',
|
||||
]);
|
||||
|
||||
return $keywords;
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\DBAL\Platforms;
|
||||
|
||||
use Doctrine\DBAL\SQL\Builder\SelectSQLBuilder;
|
||||
|
||||
use function implode;
|
||||
|
||||
/**
|
||||
* Provides the behavior, features and SQL dialect of the MariaDB 10.10 database platform.
|
||||
*/
|
||||
class MariaDb1010Platform extends MariaDb1060Platform
|
||||
{
|
||||
public function createSelectSQLBuilder(): SelectSQLBuilder
|
||||
{
|
||||
return AbstractPlatform::createSelectSQLBuilder();
|
||||
}
|
||||
|
||||
public function fetchTableOptionsByTable(bool $includeTableName): string
|
||||
{
|
||||
// MariaDB-10.10.1 added FULL_COLLATION_NAME to the information_schema.COLLATION_CHARACTER_SET_APPLICABILITY.
|
||||
// A base collation like uca1400_ai_ci can refer to multiple character sets. The value in the
|
||||
// information_schema.TABLES.TABLE_COLLATION corresponds to the full collation name.
|
||||
$sql = <<<'SQL'
|
||||
SELECT t.TABLE_NAME,
|
||||
t.ENGINE,
|
||||
t.AUTO_INCREMENT,
|
||||
t.TABLE_COMMENT,
|
||||
t.CREATE_OPTIONS,
|
||||
t.TABLE_COLLATION,
|
||||
ccsa.CHARACTER_SET_NAME
|
||||
FROM information_schema.TABLES t
|
||||
INNER JOIN information_schema.COLLATION_CHARACTER_SET_APPLICABILITY ccsa
|
||||
ON ccsa.FULL_COLLATION_NAME = t.TABLE_COLLATION
|
||||
SQL;
|
||||
|
||||
$conditions = ['t.TABLE_SCHEMA = ?'];
|
||||
|
||||
if ($includeTableName) {
|
||||
$conditions[] = 't.TABLE_NAME = ?';
|
||||
}
|
||||
|
||||
$conditions[] = "t.TABLE_TYPE = 'BASE TABLE'";
|
||||
|
||||
return $sql . ' WHERE ' . implode(' AND ', $conditions);
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -3,9 +3,7 @@
|
||||
namespace Doctrine\DBAL\Platforms;
|
||||
|
||||
/**
|
||||
* Provides the behavior, features and SQL dialect of the MariaDB 10.2 (10.2.7 GA) database platform.
|
||||
*
|
||||
* Note: Should not be used with versions prior to 10.2.7.
|
||||
* Provides the behavior, features and SQL dialect of the MariaDB 10.2 database platform.
|
||||
*
|
||||
* @deprecated This class will be merged with {@see MariaDBPlatform} in 4.0 because support for MariaDB
|
||||
* releases prior to 10.4.3 will be dropped.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ use Doctrine\Deprecations\Deprecation;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Provides the behavior, features and SQL dialect of the MariaDB 10.4 (10.4.6 GA) database platform.
|
||||
* Provides the behavior, features and SQL dialect of the MariaDB 10.4 database platform.
|
||||
*
|
||||
* Extend deprecated MariaDb1027Platform to ensure correct functions used in MySQLSchemaManager which
|
||||
* tests for MariaDb1027Platform not MariaDBPlatform.
|
||||
|
||||
+1
-3
@@ -6,9 +6,7 @@ use Doctrine\DBAL\Schema\Index;
|
||||
use Doctrine\DBAL\Schema\TableDiff;
|
||||
|
||||
/**
|
||||
* Provides the behavior, features and SQL dialect of the MariaDB 10.5 (10.5.2 GA) database platform.
|
||||
*
|
||||
* Note: Should not be used with versions prior to 10.5.2.
|
||||
* Provides the behavior, features and SQL dialect of the MariaDB 10.5 database platform.
|
||||
*/
|
||||
class MariaDb1052Platform extends MariaDb1043Platform
|
||||
{
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ namespace Doctrine\DBAL\Platforms;
|
||||
use Doctrine\DBAL\SQL\Builder\SelectSQLBuilder;
|
||||
|
||||
/**
|
||||
* Provides the behavior, features and SQL dialect of the MariaDB 10.6 (10.6.0 GA) database platform.
|
||||
* Provides the behavior, features and SQL dialect of the MariaDB 10.6 database platform.
|
||||
*/
|
||||
class MariaDb1060Platform extends MariaDb1052Platform
|
||||
{
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
|
||||
/**
|
||||
* Provides the behavior, features and SQL dialect of the MySQL 5.7 (5.7.9 GA) database platform.
|
||||
* Provides the behavior, features and SQL dialect of the MySQL 5.7 database platform.
|
||||
*
|
||||
* @deprecated This class will be merged with {@see MySQLPlatform} in 4.0 because support for MySQL
|
||||
* releases prior to 5.7 will be dropped.
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ use Doctrine\DBAL\SQL\Builder\SelectSQLBuilder;
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
|
||||
/**
|
||||
* Provides the behavior, features and SQL dialect of the MySQL 8.0 (8.0 GA) database platform.
|
||||
* Provides the behavior, features and SQL dialect of the MySQL 8.0 database platform.
|
||||
*/
|
||||
class MySQL80Platform extends MySQL57Platform
|
||||
{
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\DBAL\Platforms;
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
|
||||
/**
|
||||
* Provides the behavior, features and SQL dialect of the MySQL 8.4 database platform.
|
||||
*/
|
||||
class MySQL84Platform extends MySQL80Platform
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @deprecated Implement {@see createReservedKeywordsList()} instead.
|
||||
*/
|
||||
protected function getReservedKeywordsClass()
|
||||
{
|
||||
Deprecation::triggerIfCalledFromOutside(
|
||||
'doctrine/dbal',
|
||||
'https://github.com/doctrine/dbal/issues/4510',
|
||||
'MySQL84Platform::getReservedKeywordsClass() is deprecated,'
|
||||
. ' use MySQL84Platform::createReservedKeywordsList() instead.',
|
||||
);
|
||||
|
||||
return Keywords\MySQL84Keywords::class;
|
||||
}
|
||||
}
|
||||
@@ -473,8 +473,6 @@ class OraclePlatform extends AbstractPlatform
|
||||
* @deprecated The SQL used for schema introspection is an implementation detail and should not be relied upon.
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaOracleReader.html
|
||||
*/
|
||||
public function getListTableIndexesSQL($table, $database = null)
|
||||
{
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\DBAL\Platforms;
|
||||
|
||||
/**
|
||||
* Provides the behavior, features and SQL dialect of the PostgreSQL 12.0 database platform.
|
||||
*/
|
||||
class PostgreSQL120Platform extends PostgreSQL100Platform
|
||||
{
|
||||
public function getDefaultColumnValueSQLSnippet(): string
|
||||
{
|
||||
// in case of GENERATED ALWAYS AS (foobar) STORED column (added in PostgreSQL 12.0)
|
||||
// PostgreSQL's pg_get_expr(adbin, adrelid) will return the 'foobar' part
|
||||
// which is not the 'default' value of the column but its 'definition'
|
||||
// so in that case we force it to NULL as DBAL will use that column only for the
|
||||
// 'default' value
|
||||
return <<<'SQL'
|
||||
SELECT
|
||||
CASE
|
||||
WHEN a.attgenerated = 's' THEN NULL
|
||||
ELSE pg_get_expr(adbin, adrelid)
|
||||
END
|
||||
FROM pg_attrdef
|
||||
WHERE c.oid = pg_attrdef.adrelid
|
||||
AND pg_attrdef.adnum=a.attnum
|
||||
SQL;
|
||||
}
|
||||
}
|
||||
+13
-2
@@ -405,8 +405,6 @@ SQL
|
||||
* @deprecated The SQL used for schema introspection is an implementation detail and should not be relied upon.
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
|
||||
*/
|
||||
public function getListTableIndexesSQL($table, $database = null)
|
||||
{
|
||||
@@ -1193,6 +1191,19 @@ SQL
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the snippet used to retrieve the default value for a given column
|
||||
*/
|
||||
public function getDefaultColumnValueSQLSnippet(): string
|
||||
{
|
||||
return <<<'SQL'
|
||||
SELECT pg_get_expr(adbin, adrelid)
|
||||
FROM pg_attrdef
|
||||
WHERE c.oid = pg_attrdef.adrelid
|
||||
AND pg_attrdef.adnum=a.attnum
|
||||
SQL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
||||
+55
-45
@@ -38,9 +38,12 @@ use function is_string;
|
||||
use function preg_match;
|
||||
use function preg_match_all;
|
||||
use function sprintf;
|
||||
use function str_ends_with;
|
||||
use function str_replace;
|
||||
use function str_starts_with;
|
||||
use function strpos;
|
||||
use function strtoupper;
|
||||
use function substr;
|
||||
use function substr_count;
|
||||
|
||||
use const PREG_OFFSET_CAPTURE;
|
||||
@@ -399,6 +402,13 @@ class SQLServerPlatform extends AbstractPlatform
|
||||
return $sql . ' (' . $this->getIndexFieldDeclarationListSQL($index) . ')';
|
||||
}
|
||||
|
||||
private function unquoteSingleIdentifier(string $possiblyQuotedName): string
|
||||
{
|
||||
return str_starts_with($possiblyQuotedName, '[') && str_ends_with($possiblyQuotedName, ']')
|
||||
? substr($possiblyQuotedName, 1, -1)
|
||||
: $possiblyQuotedName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL statement for creating a column comment.
|
||||
*
|
||||
@@ -419,23 +429,20 @@ class SQLServerPlatform extends AbstractPlatform
|
||||
protected function getCreateColumnCommentSQL($tableName, $columnName, $comment)
|
||||
{
|
||||
if (strpos($tableName, '.') !== false) {
|
||||
[$schemaSQL, $tableSQL] = explode('.', $tableName);
|
||||
$schemaSQL = $this->quoteStringLiteral($schemaSQL);
|
||||
$tableSQL = $this->quoteStringLiteral($tableSQL);
|
||||
[$schemaName, $tableName] = explode('.', $tableName);
|
||||
} else {
|
||||
$schemaSQL = "'dbo'";
|
||||
$tableSQL = $this->quoteStringLiteral($tableName);
|
||||
$schemaName = 'dbo';
|
||||
}
|
||||
|
||||
return $this->getAddExtendedPropertySQL(
|
||||
'MS_Description',
|
||||
$comment,
|
||||
'SCHEMA',
|
||||
$schemaSQL,
|
||||
$this->quoteStringLiteral($this->unquoteSingleIdentifier($schemaName)),
|
||||
'TABLE',
|
||||
$tableSQL,
|
||||
$this->quoteStringLiteral($this->unquoteSingleIdentifier($tableName)),
|
||||
'COLUMN',
|
||||
$columnName,
|
||||
$this->quoteStringLiteral($this->unquoteSingleIdentifier($columnName)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -806,23 +813,20 @@ class SQLServerPlatform extends AbstractPlatform
|
||||
protected function getAlterColumnCommentSQL($tableName, $columnName, $comment)
|
||||
{
|
||||
if (strpos($tableName, '.') !== false) {
|
||||
[$schemaSQL, $tableSQL] = explode('.', $tableName);
|
||||
$schemaSQL = $this->quoteStringLiteral($schemaSQL);
|
||||
$tableSQL = $this->quoteStringLiteral($tableSQL);
|
||||
[$schemaName, $tableName] = explode('.', $tableName);
|
||||
} else {
|
||||
$schemaSQL = "'dbo'";
|
||||
$tableSQL = $this->quoteStringLiteral($tableName);
|
||||
$schemaName = 'dbo';
|
||||
}
|
||||
|
||||
return $this->getUpdateExtendedPropertySQL(
|
||||
'MS_Description',
|
||||
$comment,
|
||||
'SCHEMA',
|
||||
$schemaSQL,
|
||||
$this->quoteStringLiteral($this->unquoteSingleIdentifier($schemaName)),
|
||||
'TABLE',
|
||||
$tableSQL,
|
||||
$this->quoteStringLiteral($this->unquoteSingleIdentifier($tableName)),
|
||||
'COLUMN',
|
||||
$columnName,
|
||||
$this->quoteStringLiteral($this->unquoteSingleIdentifier($columnName)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -845,22 +849,19 @@ class SQLServerPlatform extends AbstractPlatform
|
||||
protected function getDropColumnCommentSQL($tableName, $columnName)
|
||||
{
|
||||
if (strpos($tableName, '.') !== false) {
|
||||
[$schemaSQL, $tableSQL] = explode('.', $tableName);
|
||||
$schemaSQL = $this->quoteStringLiteral($schemaSQL);
|
||||
$tableSQL = $this->quoteStringLiteral($tableSQL);
|
||||
[$schemaName, $tableName] = explode('.', $tableName);
|
||||
} else {
|
||||
$schemaSQL = "'dbo'";
|
||||
$tableSQL = $this->quoteStringLiteral($tableName);
|
||||
$schemaName = 'dbo';
|
||||
}
|
||||
|
||||
return $this->getDropExtendedPropertySQL(
|
||||
'MS_Description',
|
||||
'SCHEMA',
|
||||
$schemaSQL,
|
||||
$this->quoteStringLiteral($this->unquoteSingleIdentifier($schemaName)),
|
||||
'TABLE',
|
||||
$tableSQL,
|
||||
$this->quoteStringLiteral($this->unquoteSingleIdentifier($tableName)),
|
||||
'COLUMN',
|
||||
$columnName,
|
||||
$this->quoteStringLiteral($this->unquoteSingleIdentifier($columnName)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -907,10 +908,13 @@ class SQLServerPlatform extends AbstractPlatform
|
||||
$level2Name = null
|
||||
) {
|
||||
return 'EXEC sp_addextendedproperty ' .
|
||||
'N' . $this->quoteStringLiteral($name) . ', N' . $this->quoteStringLiteral((string) $value) . ', ' .
|
||||
'N' . $this->quoteStringLiteral((string) $level0Type) . ', ' . $level0Name . ', ' .
|
||||
'N' . $this->quoteStringLiteral((string) $level1Type) . ', ' . $level1Name . ', ' .
|
||||
'N' . $this->quoteStringLiteral((string) $level2Type) . ', ' . $level2Name;
|
||||
'N' . $this->quoteStringLiteral($name) . ', N' . $this->quoteStringLiteral($value ?? '') . ', ' .
|
||||
'N' . $this->quoteStringLiteral($level0Type ?? '') . ', ' . $level0Name . ', ' .
|
||||
'N' . $this->quoteStringLiteral($level1Type ?? '') . ', ' . $level1Name .
|
||||
($level2Type !== null || $level2Name !== null
|
||||
? ', N' . $this->quoteStringLiteral($level2Type ?? '') . ', ' . $level2Name
|
||||
: ''
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -941,9 +945,12 @@ class SQLServerPlatform extends AbstractPlatform
|
||||
) {
|
||||
return 'EXEC sp_dropextendedproperty ' .
|
||||
'N' . $this->quoteStringLiteral($name) . ', ' .
|
||||
'N' . $this->quoteStringLiteral((string) $level0Type) . ', ' . $level0Name . ', ' .
|
||||
'N' . $this->quoteStringLiteral((string) $level1Type) . ', ' . $level1Name . ', ' .
|
||||
'N' . $this->quoteStringLiteral((string) $level2Type) . ', ' . $level2Name;
|
||||
'N' . $this->quoteStringLiteral($level0Type ?? '') . ', ' . $level0Name . ', ' .
|
||||
'N' . $this->quoteStringLiteral($level1Type ?? '') . ', ' . $level1Name .
|
||||
($level2Type !== null || $level2Name !== null
|
||||
? ', N' . $this->quoteStringLiteral($level2Type ?? '') . ', ' . $level2Name
|
||||
: ''
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -975,10 +982,13 @@ class SQLServerPlatform extends AbstractPlatform
|
||||
$level2Name = null
|
||||
) {
|
||||
return 'EXEC sp_updateextendedproperty ' .
|
||||
'N' . $this->quoteStringLiteral($name) . ', N' . $this->quoteStringLiteral((string) $value) . ', ' .
|
||||
'N' . $this->quoteStringLiteral((string) $level0Type) . ', ' . $level0Name . ', ' .
|
||||
'N' . $this->quoteStringLiteral((string) $level1Type) . ', ' . $level1Name . ', ' .
|
||||
'N' . $this->quoteStringLiteral((string) $level2Type) . ', ' . $level2Name;
|
||||
'N' . $this->quoteStringLiteral($name) . ', N' . $this->quoteStringLiteral($value ?? '') . ', ' .
|
||||
'N' . $this->quoteStringLiteral($level0Type ?? '') . ', ' . $level0Name . ', ' .
|
||||
'N' . $this->quoteStringLiteral($level1Type ?? '') . ', ' . $level1Name .
|
||||
($level2Type !== null || $level2Name !== null
|
||||
? ', N' . $this->quoteStringLiteral($level2Type ?? '') . ', ' . $level2Name
|
||||
: ''
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1296,7 +1306,7 @@ class SQLServerPlatform extends AbstractPlatform
|
||||
{
|
||||
$length = $column['length'] ?? null;
|
||||
|
||||
if (! isset($column['fixed'])) {
|
||||
if (empty($column['fixed'])) {
|
||||
return sprintf('VARCHAR(%d)', $length ?? 255);
|
||||
}
|
||||
|
||||
@@ -1549,12 +1559,14 @@ class SQLServerPlatform extends AbstractPlatform
|
||||
'smalldatetime' => Types::DATETIME_MUTABLE,
|
||||
'smallint' => Types::SMALLINT,
|
||||
'smallmoney' => Types::INTEGER,
|
||||
'sysname' => Types::STRING,
|
||||
'text' => Types::TEXT,
|
||||
'time' => Types::TIME_MUTABLE,
|
||||
'tinyint' => Types::SMALLINT,
|
||||
'uniqueidentifier' => Types::GUID,
|
||||
'varbinary' => Types::BINARY,
|
||||
'varchar' => Types::STRING,
|
||||
'xml' => Types::TEXT,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1765,15 +1777,13 @@ class SQLServerPlatform extends AbstractPlatform
|
||||
|
||||
protected function getCommentOnTableSQL(string $tableName, ?string $comment): string
|
||||
{
|
||||
return sprintf(
|
||||
<<<'SQL'
|
||||
EXEC sys.sp_addextendedproperty @name=N'MS_Description',
|
||||
@value=N%s, @level0type=N'SCHEMA', @level0name=N'dbo',
|
||||
@level1type=N'TABLE', @level1name=N%s
|
||||
SQL
|
||||
,
|
||||
$this->quoteStringLiteral((string) $comment),
|
||||
$this->quoteStringLiteral($tableName),
|
||||
return $this->getAddExtendedPropertySQL(
|
||||
'MS_Description',
|
||||
$comment,
|
||||
'SCHEMA',
|
||||
$this->quoteStringLiteral('dbo'),
|
||||
'TABLE',
|
||||
$this->quoteStringLiteral($this->unquoteSingleIdentifier($tableName)),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+11
-6
@@ -950,11 +950,6 @@ class SqlitePlatform extends AbstractPlatform
|
||||
$name = $index->getQuotedName($this);
|
||||
$columns = $index->getColumns();
|
||||
|
||||
if (strpos($table, '.') !== false) {
|
||||
[$schema, $table] = explode('.', $table);
|
||||
$name = $schema . '.' . $name;
|
||||
}
|
||||
|
||||
if (count($columns) === 0) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Incomplete or invalid index definition %s on table %s',
|
||||
@@ -967,6 +962,11 @@ class SqlitePlatform extends AbstractPlatform
|
||||
return $this->getCreatePrimaryKeySQL($index, $table);
|
||||
}
|
||||
|
||||
if (strpos($table, '.') !== false) {
|
||||
[$schema, $table] = explode('.', $table, 2);
|
||||
$name = $schema . '.' . $name;
|
||||
}
|
||||
|
||||
$query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $table;
|
||||
$query .= ' (' . $this->getIndexFieldDeclarationListSQL($index) . ')' . $this->getPartialIndexSQL($index);
|
||||
|
||||
@@ -1150,7 +1150,12 @@ class SqlitePlatform extends AbstractPlatform
|
||||
$sql = [];
|
||||
$tableSql = [];
|
||||
if (! $this->onSchemaAlterTable($diff, $tableSql)) {
|
||||
$dataTable = new Table('__temp__' . $table->getName());
|
||||
$tableName = $table->getName();
|
||||
if (strpos($tableName, '.') !== false) {
|
||||
[, $tableName] = explode('.', $tableName, 2);
|
||||
}
|
||||
|
||||
$dataTable = new Table('__temp__' . $tableName);
|
||||
|
||||
$newTable = new Table(
|
||||
$table->getQuotedName($this),
|
||||
|
||||
@@ -1734,7 +1734,7 @@ class QueryBuilder
|
||||
|
||||
/**
|
||||
* Enables caching of the results of this query, for given amount of seconds
|
||||
* and optionally specified witch key to use for the cache entry.
|
||||
* and optionally specified which key to use for the cache entry.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
|
||||
@@ -184,7 +184,7 @@ class Result
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @return Traversable<mixed, mixed>
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,8 @@ use function substr;
|
||||
* The abstract asset allows to reset the name of all assets without publishing this to the public userland.
|
||||
*
|
||||
* This encapsulation hack is necessary to keep a consistent state of the database schema. Say we have a list of tables
|
||||
* array($tableName => Table($tableName)); if you want to rename the table, you have to make sure
|
||||
* array($tableName => Table($tableName)); if you want to rename the table, you have to make sure this does not get
|
||||
* recreated during schema migration.
|
||||
*/
|
||||
abstract class AbstractAsset
|
||||
{
|
||||
|
||||
+9
-1
@@ -31,7 +31,7 @@ use function strtolower;
|
||||
* Base class for schema managers. Schema managers are used to inspect and/or
|
||||
* modify the database schema/structure.
|
||||
*
|
||||
* @template T of AbstractPlatform
|
||||
* @template-covariant T of AbstractPlatform
|
||||
*/
|
||||
abstract class AbstractSchemaManager
|
||||
{
|
||||
@@ -1740,6 +1740,10 @@ abstract class AbstractSchemaManager
|
||||
*/
|
||||
public function extractDoctrineTypeFromComment($comment, $currentType)
|
||||
{
|
||||
if ($this->_conn->getConfiguration()->getDisableTypeComments()) {
|
||||
return $currentType;
|
||||
}
|
||||
|
||||
if ($comment !== null && preg_match('(\(DC2Type:(((?!\)).)+)\))', $comment, $match) === 1) {
|
||||
return $match[1];
|
||||
}
|
||||
@@ -1757,6 +1761,10 @@ abstract class AbstractSchemaManager
|
||||
*/
|
||||
public function removeDoctrineTypeFromComment($comment, $type)
|
||||
{
|
||||
if ($this->_conn->getConfiguration()->getDisableTypeComments()) {
|
||||
return $comment;
|
||||
}
|
||||
|
||||
if ($comment === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+3
-21
@@ -557,31 +557,13 @@ SQL;
|
||||
*/
|
||||
protected function fetchTableOptionsByTable(string $databaseName, ?string $tableName = null): array
|
||||
{
|
||||
$sql = <<<'SQL'
|
||||
SELECT t.TABLE_NAME,
|
||||
t.ENGINE,
|
||||
t.AUTO_INCREMENT,
|
||||
t.TABLE_COMMENT,
|
||||
t.CREATE_OPTIONS,
|
||||
t.TABLE_COLLATION,
|
||||
ccsa.CHARACTER_SET_NAME
|
||||
FROM information_schema.TABLES t
|
||||
INNER JOIN information_schema.COLLATION_CHARACTER_SET_APPLICABILITY ccsa
|
||||
ON ccsa.COLLATION_NAME = t.TABLE_COLLATION
|
||||
SQL;
|
||||
|
||||
$conditions = ['t.TABLE_SCHEMA = ?'];
|
||||
$params = [$databaseName];
|
||||
$sql = $this->_platform->fetchTableOptionsByTable($tableName !== null);
|
||||
|
||||
$params = [$databaseName];
|
||||
if ($tableName !== null) {
|
||||
$conditions[] = 't.TABLE_NAME = ?';
|
||||
$params[] = $tableName;
|
||||
$params[] = $tableName;
|
||||
}
|
||||
|
||||
$conditions[] = "t.TABLE_TYPE = 'BASE TABLE'";
|
||||
|
||||
$sql .= ' WHERE ' . implode(' AND ', $conditions);
|
||||
|
||||
/** @var array<string,array<string,mixed>> $metadata */
|
||||
$metadata = $this->_conn->executeQuery($sql, $params)
|
||||
->fetchAllAssociativeIndexed();
|
||||
|
||||
@@ -107,8 +107,6 @@ class OracleSchemaManager extends AbstractSchemaManager
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
|
||||
*/
|
||||
protected function _getPortableTableIndexesList($tableIndexes, $tableName = null)
|
||||
{
|
||||
|
||||
+4
-9
@@ -287,8 +287,6 @@ SQL,
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
|
||||
*/
|
||||
protected function _getPortableTableIndexesList($tableIndexes, $tableName = null)
|
||||
{
|
||||
@@ -463,6 +461,7 @@ SQL,
|
||||
$length = null;
|
||||
break;
|
||||
|
||||
case 'json':
|
||||
case 'text':
|
||||
case '_varchar':
|
||||
case 'varchar':
|
||||
@@ -616,7 +615,7 @@ SQL;
|
||||
$sql .= ' c.relname AS table_name, n.nspname AS schema_name,';
|
||||
}
|
||||
|
||||
$sql .= <<<'SQL'
|
||||
$sql .= sprintf(<<<'SQL'
|
||||
a.attnum,
|
||||
quote_ident(a.attname) AS field,
|
||||
t.typname AS type,
|
||||
@@ -632,11 +631,7 @@ SQL;
|
||||
AND pg_index.indkey[0] = a.attnum
|
||||
AND pg_index.indisprimary = 't'
|
||||
) AS pri,
|
||||
(SELECT pg_get_expr(adbin, adrelid)
|
||||
FROM pg_attrdef
|
||||
WHERE c.oid = pg_attrdef.adrelid
|
||||
AND pg_attrdef.adnum=a.attnum
|
||||
) AS default,
|
||||
(%s) AS default,
|
||||
(SELECT pg_description.description
|
||||
FROM pg_description WHERE pg_description.objoid = c.oid AND a.attnum = pg_description.objsubid
|
||||
) AS comment
|
||||
@@ -651,7 +646,7 @@ SQL;
|
||||
ON d.objid = c.oid
|
||||
AND d.deptype = 'e'
|
||||
AND d.classid = (SELECT oid FROM pg_class WHERE relname = 'pg_class')
|
||||
SQL;
|
||||
SQL, $this->_platform->getDefaultColumnValueSQLSnippet());
|
||||
|
||||
$conditions = array_merge([
|
||||
'a.attnum > 0',
|
||||
|
||||
+2
-4
@@ -202,7 +202,7 @@ class SqliteSchemaManager extends AbstractSchemaManager
|
||||
{
|
||||
$table = $this->normalizeName($table);
|
||||
|
||||
$columns = $this->selectForeignKeyColumns('', $table)
|
||||
$columns = $this->selectForeignKeyColumns($database ?? 'main', $table)
|
||||
->fetchAllAssociative();
|
||||
|
||||
if (count($columns) > 0) {
|
||||
@@ -222,8 +222,6 @@ class SqliteSchemaManager extends AbstractSchemaManager
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
|
||||
*/
|
||||
protected function _getPortableTableIndexesList($tableIndexes, $tableName = null)
|
||||
{
|
||||
@@ -744,7 +742,7 @@ SQL;
|
||||
p.*
|
||||
FROM sqlite_master t
|
||||
JOIN pragma_foreign_key_list(t.name) p
|
||||
ON p."seq" != "-1"
|
||||
ON p."seq" != '-1'
|
||||
SQL;
|
||||
|
||||
$conditions = [
|
||||
|
||||
Vendored
+3
@@ -9,6 +9,7 @@ use Doctrine\DBAL\Platforms\Keywords\KeywordList;
|
||||
use Doctrine\DBAL\Platforms\Keywords\MariaDb102Keywords;
|
||||
use Doctrine\DBAL\Platforms\Keywords\MySQL57Keywords;
|
||||
use Doctrine\DBAL\Platforms\Keywords\MySQL80Keywords;
|
||||
use Doctrine\DBAL\Platforms\Keywords\MySQL84Keywords;
|
||||
use Doctrine\DBAL\Platforms\Keywords\MySQLKeywords;
|
||||
use Doctrine\DBAL\Platforms\Keywords\OracleKeywords;
|
||||
use Doctrine\DBAL\Platforms\Keywords\PostgreSQL100Keywords;
|
||||
@@ -59,6 +60,7 @@ class ReservedWordsCommand extends Command
|
||||
'mysql' => new MySQLKeywords(),
|
||||
'mysql57' => new MySQL57Keywords(),
|
||||
'mysql80' => new MySQL80Keywords(),
|
||||
'mysql84' => new MySQL84Keywords(),
|
||||
'oracle' => new OracleKeywords(),
|
||||
'pgsql' => new PostgreSQL94Keywords(),
|
||||
'pgsql100' => new PostgreSQL100Keywords(),
|
||||
@@ -130,6 +132,7 @@ The following keyword lists are currently shipped with Doctrine:
|
||||
* mysql
|
||||
* mysql57
|
||||
* mysql80
|
||||
* mysql84
|
||||
* oracle
|
||||
* pgsql
|
||||
* pgsql100
|
||||
|
||||
@@ -11,18 +11,19 @@ use Doctrine\Deprecations\Deprecation;
|
||||
use function get_class;
|
||||
|
||||
/**
|
||||
* DateTime type saving additional timezone information.
|
||||
* DateTime type accepting additional information about timezone offsets.
|
||||
*
|
||||
* Caution: Databases are not necessarily experts at storing timezone related
|
||||
* data of dates. First, of all the supported vendors only PostgreSQL and Oracle
|
||||
* support storing Timezone data. But those two don't save the actual timezone
|
||||
* attached to a DateTime instance (for example "Europe/Berlin" or "America/Montreal")
|
||||
* but the current offset of them related to UTC. That means depending on daylight saving times
|
||||
* or not you may get different offsets.
|
||||
* data of dates. First, of not all the supported vendors support storing Timezone data, and some of
|
||||
* them only use the offset to calculate the timestamp in its default timezone (usually UTC) and persist
|
||||
* the value without the offset information. They even don't save the actual timezone names attached
|
||||
* to a DateTime instance (for example "Europe/Berlin" or "America/Montreal") but the current offset
|
||||
* of them related to UTC. That means, depending on daylight saving times or not, you may get different
|
||||
* offsets.
|
||||
*
|
||||
* This datatype makes only sense to use, if your application works with an offset, not
|
||||
* with an actual timezone that uses transitions. Otherwise your DateTime instance
|
||||
* attached with a timezone such as Europe/Berlin gets saved into the database with
|
||||
* This datatype makes only sense to use, if your application only needs to accept the timezone offset,
|
||||
* not the actual timezone that uses transitions. Otherwise your DateTime instance
|
||||
* attached with a timezone such as "Europe/Berlin" gets saved into the database with
|
||||
* the offset and re-created from persistence with only the offset, not the original timezone
|
||||
* attached.
|
||||
*/
|
||||
|
||||
@@ -150,6 +150,67 @@ class MyTest extends TestCase
|
||||
}
|
||||
```
|
||||
|
||||
## Displaying deprecations after running a PHPUnit test suite
|
||||
|
||||
It is possible to integrate this library with PHPUnit to display all
|
||||
deprecations triggered during the test suite execution.
|
||||
|
||||
```xml
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
colors="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||
failOnDeprecation="true"
|
||||
>
|
||||
<!-- one attribute to display the deprecations, the other to fail the test suite -->
|
||||
|
||||
<php>
|
||||
<!-- ensures native PHP deprecations are used -->
|
||||
<server name="DOCTRINE_DEPRECATIONS" value="trigger"/>
|
||||
</php>
|
||||
|
||||
<!-- ensures the @ operator in @trigger_error is ignored -->
|
||||
<source ignoreSuppressionOfDeprecations="true">
|
||||
<include>
|
||||
<directory>src</directory>
|
||||
</include>
|
||||
</source>
|
||||
</phpunit>
|
||||
```
|
||||
|
||||
Note that you can still trigger Deprecations in your code, provided you use the
|
||||
`#[WithoutErrorHandler]` attribute to disable PHPUnit's error handler for tests
|
||||
that call it. Be wary that this will disable all error handling, meaning it
|
||||
will mask any warnings or errors that would otherwise be caught by PHPUnit.
|
||||
|
||||
At the moment, it is not possible to disable deduplication with an environment
|
||||
variable, but you can use a bootstrap file to achieve that:
|
||||
|
||||
```php
|
||||
// tests/bootstrap.php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
|
||||
Deprecation::withoutDeduplication();
|
||||
```
|
||||
|
||||
Then, reference that file in your PHPUnit configuration:
|
||||
|
||||
```xml
|
||||
<phpunit …
|
||||
bootstrap="tests/bootstrap.php"
|
||||
…
|
||||
>
|
||||
…
|
||||
</phpunit>
|
||||
```
|
||||
|
||||
## What is a deprecation identifier?
|
||||
|
||||
An identifier for deprecations is just a link to any resource, most often a
|
||||
|
||||
@@ -8,20 +8,18 @@
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9",
|
||||
"phpstan/phpstan": "1.4.10 || 1.10.15",
|
||||
"phpstan/phpstan-phpunit": "^1.0",
|
||||
"doctrine/coding-standard": "^9 || ^12",
|
||||
"phpstan/phpstan": "1.4.10 || 2.0.3",
|
||||
"phpstan/phpstan-phpunit": "^1.0 || ^2",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
||||
"psalm/plugin-phpunit": "0.18.4",
|
||||
"psr/log": "^1 || ^2 || ^3",
|
||||
"vimeo/psalm": "4.30.0 || 5.12.0"
|
||||
"psr/log": "^1 || ^2 || ^3"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "Allows logging deprecations via PSR-3 logger implementation"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations"
|
||||
"Doctrine\\Deprecations\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
|
||||
+5
-9
@@ -173,9 +173,7 @@ class Deprecation
|
||||
self::delegateTriggerToBackend($message, $backtrace, $link, $package);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array{function: string, line?: int, file?: string, class?: class-string, type?: string, args?: mixed[], object?: object}> $backtrace
|
||||
*/
|
||||
/** @param list<array{function: string, line?: int, file?: string, class?: class-string, type?: string, args?: mixed[], object?: object}> $backtrace */
|
||||
private static function delegateTriggerToBackend(string $message, array $backtrace, string $link, string $package): void
|
||||
{
|
||||
$type = self::$type ?? self::getTypeFromEnv();
|
||||
@@ -226,19 +224,19 @@ class Deprecation
|
||||
|
||||
public static function enableTrackingDeprecations(): void
|
||||
{
|
||||
self::$type = self::$type ?? 0;
|
||||
self::$type = self::$type ?? self::getTypeFromEnv();
|
||||
self::$type |= self::TYPE_TRACK_DEPRECATIONS;
|
||||
}
|
||||
|
||||
public static function enableWithTriggerError(): void
|
||||
{
|
||||
self::$type = self::$type ?? 0;
|
||||
self::$type = self::$type ?? self::getTypeFromEnv();
|
||||
self::$type |= self::TYPE_TRIGGER_ERROR;
|
||||
}
|
||||
|
||||
public static function enableWithPsrLogger(LoggerInterface $logger): void
|
||||
{
|
||||
self::$type = self::$type ?? 0;
|
||||
self::$type = self::$type ?? self::getTypeFromEnv();
|
||||
self::$type |= self::TYPE_PSR_LOGGER;
|
||||
self::$logger = $logger;
|
||||
}
|
||||
@@ -289,9 +287,7 @@ class Deprecation
|
||||
return self::$triggeredDeprecations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int-mask-of<self::TYPE_*>
|
||||
*/
|
||||
/** @return int-mask-of<self::TYPE_*> */
|
||||
private static function getTypeFromEnv(): int
|
||||
{
|
||||
switch ($_SERVER['DOCTRINE_DEPRECATIONS'] ?? $_ENV['DOCTRINE_DEPRECATIONS'] ?? null) {
|
||||
+2
-6
@@ -26,17 +26,13 @@ trait VerifyDeprecations
|
||||
$this->doctrineNoDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @before
|
||||
*/
|
||||
/** @before */
|
||||
public function enableDeprecationTracking(): void
|
||||
{
|
||||
Deprecation::enableTrackingDeprecations();
|
||||
}
|
||||
|
||||
/**
|
||||
* @after
|
||||
*/
|
||||
/** @after */
|
||||
public function verifyDeprecationsAreTriggered(): void
|
||||
{
|
||||
foreach ($this->doctrineDeprecationsExpectations as $identifier => $expectation) {
|
||||
@@ -41,10 +41,10 @@
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^10",
|
||||
"doctrine/coding-standard": "^12",
|
||||
"phpstan/phpstan": "^1.8.8",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"vimeo/psalm": "^4.28"
|
||||
"phpunit/phpunit": "^10.5",
|
||||
"vimeo/psalm": "^5.24"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/common": "<2.9"
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
parameters:
|
||||
level: 9
|
||||
paths:
|
||||
- src/
|
||||
- tests/
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="5.24.0@462c80e31c34e58cc4f750c656be3927e80e550e">
|
||||
<file src="src/EventManager.php">
|
||||
<RiskyTruthyFalsyComparison>
|
||||
<code><![CDATA[empty($this->listeners[$event])]]></code>
|
||||
</RiskyTruthyFalsyComparison>
|
||||
</file>
|
||||
</files>
|
||||
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
errorLevel="2"
|
||||
resolveFromConfigFile="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
</psalm>
|
||||
@@ -0,0 +1,24 @@
|
||||
Dompdf was designed and developed by Benj Carson.
|
||||
|
||||
### Current Team
|
||||
|
||||
* **Brian Sweeney** (maintainer)
|
||||
* **Till Berger**
|
||||
|
||||
### Alumni
|
||||
|
||||
* **Benj Carson** (creator)
|
||||
* **Fabien Ménager**
|
||||
* **Simon Berger**
|
||||
* **Orion Richardson**
|
||||
|
||||
### Contributors
|
||||
* **Gabriel Bull**
|
||||
* **Barry vd. Heuvel**
|
||||
* **Ryan H. Masten**
|
||||
* **Helmut Tischer**
|
||||
* [and many more...](https://github.com/dompdf/dompdf/graphs/contributors)
|
||||
|
||||
### Thanks
|
||||
|
||||
Dompdf would not have been possible without strong community support.
|
||||
@@ -0,0 +1,456 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
@@ -0,0 +1,232 @@
|
||||
Dompdf
|
||||
======
|
||||
|
||||
[](https://github.com/dompdf/dompdf/actions/workflows/test.yml)
|
||||
[](https://packagist.org/packages/dompdf/dompdf)
|
||||
[](https://packagist.org/packages/dompdf/dompdf)
|
||||
[](https://packagist.org/packages/dompdf/dompdf)
|
||||
|
||||
**Dompdf is an HTML to PDF converter**
|
||||
|
||||
At its heart, dompdf is (mostly) a [CSS 2.1](http://www.w3.org/TR/CSS2/) compliant
|
||||
HTML layout and rendering engine written in PHP. It is a style-driven renderer:
|
||||
it will download and read external stylesheets, inline style tags, and the style
|
||||
attributes of individual HTML elements. It also supports most presentational
|
||||
HTML attributes.
|
||||
|
||||
*This document applies to the latest stable code which may not reflect the current
|
||||
release. For released code please
|
||||
[navigate to the appropriate tag](https://github.com/dompdf/dompdf/tags).*
|
||||
|
||||
----
|
||||
|
||||
**Check out the [demo](http://eclecticgeek.com/dompdf/debug.php) and ask any
|
||||
question on [StackOverflow](https://stackoverflow.com/questions/tagged/dompdf) or
|
||||
in [Discussions](https://github.com/dompdf/dompdf/discussions).**
|
||||
|
||||
Follow us on [](http://www.twitter.com/dompdf).
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
* Handles most CSS 2.1 and a few CSS3 properties, including @import, @media &
|
||||
@page rules
|
||||
* Supports most presentational HTML 4.0 attributes
|
||||
* Supports external stylesheets, either local or through http/ftp (via
|
||||
fopen-wrappers)
|
||||
* Supports complex tables, including row & column spans, separate & collapsed
|
||||
border models, individual cell styling
|
||||
* Image support (gif, png (8, 24 and 32 bit with alpha channel), bmp & jpeg)
|
||||
* No dependencies on external PDF libraries, thanks to the R&OS PDF class
|
||||
* Inline PHP support
|
||||
* Basic SVG support (see "Limitations" below)
|
||||
|
||||
## Requirements
|
||||
|
||||
* PHP version 7.1 or higher
|
||||
* DOM extension
|
||||
* MBString extension
|
||||
* php-font-lib
|
||||
* php-svg-lib
|
||||
|
||||
Note that some required dependencies may have further dependencies
|
||||
(notably php-svg-lib requires sabberworm/php-css-parser).
|
||||
|
||||
### Recommendations
|
||||
|
||||
* OPcache (OPcache, XCache, APC, etc.): improves performance
|
||||
* GD (for image processing)
|
||||
* IMagick or GMagick extension: improves image processing performance
|
||||
|
||||
Visit the wiki for more information:
|
||||
https://github.com/dompdf/dompdf/wiki/Requirements
|
||||
|
||||
## About Fonts & Character Encoding
|
||||
|
||||
PDF documents internally support the following fonts: Helvetica, Times-Roman,
|
||||
Courier, Zapf-Dingbats, & Symbol. These fonts only support Windows ANSI
|
||||
encoding. In order for a PDF to display characters that are not available in
|
||||
Windows ANSI, you must supply an external font. Dompdf will embed any referenced
|
||||
font in the PDF so long as it has been pre-loaded or is accessible to dompdf and
|
||||
reference in CSS @font-face rules. See the
|
||||
[font overview](https://github.com/dompdf/dompdf/wiki/About-Fonts-and-Character-Encoding)
|
||||
for more information on how to use fonts.
|
||||
|
||||
The [DejaVu TrueType fonts](https://dejavu-fonts.github.io/) have been pre-installed
|
||||
to give dompdf decent Unicode character coverage by default. To use the DejaVu
|
||||
fonts reference the font in your stylesheet, e.g. `body { font-family: DejaVu
|
||||
Sans; }` (for DejaVu Sans). The following DejaVu 2.34 fonts are available:
|
||||
DejaVu Sans, DejaVu Serif, and DejaVu Sans Mono.
|
||||
|
||||
## Easy Installation
|
||||
|
||||
### Install with composer
|
||||
|
||||
To install with [Composer](https://getcomposer.org/), simply require the
|
||||
latest version of this package.
|
||||
|
||||
```bash
|
||||
composer require dompdf/dompdf
|
||||
```
|
||||
|
||||
Make sure that the autoload file from Composer is loaded.
|
||||
|
||||
```php
|
||||
// somewhere early in your project's loading, require the Composer autoloader
|
||||
// see: http://getcomposer.org/doc/00-intro.md
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
```
|
||||
|
||||
### Download and install
|
||||
|
||||
Download a packaged archive of dompdf and extract it into the
|
||||
directory where dompdf will reside
|
||||
|
||||
* You can download stable copies of dompdf from
|
||||
https://github.com/dompdf/dompdf/releases
|
||||
* Or download a nightly (the latest, unreleased code) from
|
||||
http://eclecticgeek.com/dompdf
|
||||
|
||||
Use the packaged release autoloader to load dompdf, libraries,
|
||||
and helper functions in your PHP:
|
||||
|
||||
```php
|
||||
// include autoloader
|
||||
require_once 'dompdf/autoload.inc.php';
|
||||
```
|
||||
|
||||
Note: packaged releases are named according using semantic
|
||||
versioning (_dompdf_MAJOR-MINOR-PATCH.zip_). So the 1.0.0
|
||||
release would be dompdf_1-0-0.zip. This is the only download
|
||||
that includes the autoloader for Dompdf and all its dependencies.
|
||||
|
||||
### Install with git
|
||||
|
||||
From the command line, switch to the directory where dompdf will
|
||||
reside and run the following commands:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/dompdf/dompdf.git
|
||||
cd dompdf/lib
|
||||
|
||||
git clone https://github.com/PhenX/php-font-lib.git php-font-lib
|
||||
cd php-font-lib
|
||||
git checkout 0.5.1
|
||||
cd ..
|
||||
|
||||
git clone https://github.com/PhenX/php-svg-lib.git php-svg-lib
|
||||
cd php-svg-lib
|
||||
git checkout v0.3.2
|
||||
cd ..
|
||||
|
||||
git clone https://github.com/sabberworm/PHP-CSS-Parser.git php-css-parser
|
||||
cd php-css-parser
|
||||
git checkout 8.1.0
|
||||
```
|
||||
|
||||
Require dompdf and it's dependencies in your PHP.
|
||||
For details see the [autoloader in the utils project](https://github.com/dompdf/utils/blob/master/autoload.inc.php).
|
||||
|
||||
## Quick Start
|
||||
|
||||
Just pass your HTML in to dompdf and stream the output:
|
||||
|
||||
```php
|
||||
// reference the Dompdf namespace
|
||||
use Dompdf\Dompdf;
|
||||
|
||||
// instantiate and use the dompdf class
|
||||
$dompdf = new Dompdf();
|
||||
$dompdf->loadHtml('hello world');
|
||||
|
||||
// (Optional) Setup the paper size and orientation
|
||||
$dompdf->setPaper('A4', 'landscape');
|
||||
|
||||
// Render the HTML as PDF
|
||||
$dompdf->render();
|
||||
|
||||
// Output the generated PDF to Browser
|
||||
$dompdf->stream();
|
||||
```
|
||||
|
||||
### Setting Options
|
||||
|
||||
Set options during dompdf instantiation:
|
||||
|
||||
```php
|
||||
use Dompdf\Dompdf;
|
||||
use Dompdf\Options;
|
||||
|
||||
$options = new Options();
|
||||
$options->set('defaultFont', 'Courier');
|
||||
$dompdf = new Dompdf($options);
|
||||
```
|
||||
|
||||
or at run time
|
||||
|
||||
```php
|
||||
use Dompdf\Dompdf;
|
||||
|
||||
$dompdf = new Dompdf();
|
||||
$options = $dompdf->getOptions();
|
||||
$options->setDefaultFont('Courier');
|
||||
$dompdf->setOptions($options);
|
||||
```
|
||||
|
||||
See [Dompdf\Options](src/Options.php) for a list of available options.
|
||||
|
||||
### Resource Reference Requirements
|
||||
|
||||
In order to protect potentially sensitive information Dompdf imposes
|
||||
restrictions on files referenced from the local file system or the web.
|
||||
|
||||
Files accessed through web-based protocols have the following requirements:
|
||||
* The Dompdf option "isRemoteEnabled" must be set to "true"
|
||||
* PHP must either have the curl extension enabled or the
|
||||
allow_url_fopen setting set to true
|
||||
|
||||
Files accessed through the local file system have the following requirement:
|
||||
* The file must fall within the path(s) specified for the Dompdf "chroot" option
|
||||
|
||||
## Limitations (Known Issues)
|
||||
|
||||
* Table cells are not pageable, meaning a table row must fit on a single page.
|
||||
* Elements are rendered on the active page when they are parsed.
|
||||
* Embedding "raw" SVG's (`<svg><path...></svg>`) isn't working yet, you need to
|
||||
either link to an external SVG file, or use a DataURI like this:
|
||||
```php
|
||||
$html = '<img src="data:image/svg+xml;base64,' . base64_encode($svg) . '" ...>';
|
||||
```
|
||||
Watch https://github.com/dompdf/dompdf/issues/320 for progress
|
||||
* Does not support CSS flexbox.
|
||||
* Does not support CSS Grid.
|
||||
---
|
||||
|
||||
[](http://goo.gl/DSvWf)
|
||||
|
||||
*If you find this project useful, please consider making a donation.
|
||||
Any funds donated will be used to help further development on this project.)*
|
||||
@@ -0,0 +1 @@
|
||||
2.0.8
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user