mirror of
https://github.com/nextcloud/richdocuments.git
synced 2025-12-18 05:20:43 +01:00
chore: Move to actual runtime dependency file
Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
parent
2aaeac4f7c
commit
7491f79bb5
34 changed files with 4183 additions and 232 deletions
|
|
@ -10,8 +10,7 @@
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-simplexml": "*",
|
"ext-simplexml": "*"
|
||||||
"mikehaertl/php-pdftk": "^0.13.1"
|
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"roave/security-advisories": "dev-master",
|
"roave/security-advisories": "dev-master",
|
||||||
|
|
|
||||||
146
composer.lock
generated
146
composer.lock
generated
|
|
@ -4,148 +4,8 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "f00345e82d316ea492b86fb74fb09c84",
|
"content-hash": "f118a358162577fab7ee75cad4ef1383",
|
||||||
"packages": [
|
"packages": [],
|
||||||
{
|
|
||||||
"name": "mikehaertl/php-pdftk",
|
|
||||||
"version": "0.13.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/mikehaertl/php-pdftk.git",
|
|
||||||
"reference": "3851b08c1027489e48387d7c14c27bc295d98239"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/mikehaertl/php-pdftk/zipball/3851b08c1027489e48387d7c14c27bc295d98239",
|
|
||||||
"reference": "3851b08c1027489e48387d7c14c27bc295d98239",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"mikehaertl/php-shellcommand": "^1.6.3",
|
|
||||||
"mikehaertl/php-tmpfile": "^1.1.0",
|
|
||||||
"php": ">=5.3.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": ">4.0 <9.4"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"mikehaertl\\pdftk\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Michael Haertl",
|
|
||||||
"email": "haertl.mike@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "A PDF conversion and form utility based on pdftk.",
|
|
||||||
"keywords": [
|
|
||||||
"pdf",
|
|
||||||
"pdftk"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/mikehaertl/php-pdftk/issues",
|
|
||||||
"source": "https://github.com/mikehaertl/php-pdftk/tree/0.13.1"
|
|
||||||
},
|
|
||||||
"time": "2023-11-03T16:06:08+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "mikehaertl/php-shellcommand",
|
|
||||||
"version": "1.7.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/mikehaertl/php-shellcommand.git",
|
|
||||||
"reference": "e79ea528be155ffdec6f3bf1a4a46307bb49e545"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/mikehaertl/php-shellcommand/zipball/e79ea528be155ffdec6f3bf1a4a46307bb49e545",
|
|
||||||
"reference": "e79ea528be155ffdec6f3bf1a4a46307bb49e545",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">= 5.3.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": ">4.0 <=9.4"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"mikehaertl\\shellcommand\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Michael Härtl",
|
|
||||||
"email": "haertl.mike@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "An object oriented interface to shell commands",
|
|
||||||
"keywords": [
|
|
||||||
"shell"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/mikehaertl/php-shellcommand/issues",
|
|
||||||
"source": "https://github.com/mikehaertl/php-shellcommand/tree/1.7.0"
|
|
||||||
},
|
|
||||||
"time": "2023-04-19T08:25:22+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "mikehaertl/php-tmpfile",
|
|
||||||
"version": "1.2.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/mikehaertl/php-tmpfile.git",
|
|
||||||
"reference": "70a5b70b17bc0d9666388e6a551ecc93d0b40a10"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/mikehaertl/php-tmpfile/zipball/70a5b70b17bc0d9666388e6a551ecc93d0b40a10",
|
|
||||||
"reference": "70a5b70b17bc0d9666388e6a551ecc93d0b40a10",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"php": ">=5.3.0",
|
|
||||||
"phpunit/phpunit": ">4.0 <=9.4"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"mikehaertl\\tmp\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Michael Härtl",
|
|
||||||
"email": "haertl.mike@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "A convenience class for temporary files",
|
|
||||||
"keywords": [
|
|
||||||
"files"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/mikehaertl/php-tmpfile/issues",
|
|
||||||
"source": "https://github.com/mikehaertl/php-tmpfile/tree/1.2.1"
|
|
||||||
},
|
|
||||||
"time": "2021-03-01T18:26:25+00:00"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
{
|
{
|
||||||
"name": "doctrine/instantiator",
|
"name": "doctrine/instantiator",
|
||||||
|
|
@ -3121,5 +2981,5 @@
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "8.0"
|
"php": "8.0"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "2.3.0"
|
"plugin-api-version": "2.6.0"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,10 @@
|
||||||
},
|
},
|
||||||
"autoload" : {
|
"autoload" : {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"OCA\\Richdocuments\\": "../lib/",
|
"OCA\\Richdocuments\\": "../lib/"
|
||||||
"mikehaertl\\pdftk\\": "../vendor/mikehaertl/php-pdftk/src/",
|
|
||||||
"mikehaertl\\shellcommand\\": "../vendor/mikehaertl/php-shellcommand/src/"
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"mikehaertl/php-pdftk": "^0.13.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
146
composer/composer.lock
generated
146
composer/composer.lock
generated
|
|
@ -4,8 +4,148 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "d751713988987e9331980363e24189ce",
|
"content-hash": "b0ad6a743550ac81e64e6d88bfd62ae6",
|
||||||
"packages": [],
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "mikehaertl/php-pdftk",
|
||||||
|
"version": "0.13.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/mikehaertl/php-pdftk.git",
|
||||||
|
"reference": "3851b08c1027489e48387d7c14c27bc295d98239"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/mikehaertl/php-pdftk/zipball/3851b08c1027489e48387d7c14c27bc295d98239",
|
||||||
|
"reference": "3851b08c1027489e48387d7c14c27bc295d98239",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"mikehaertl/php-shellcommand": "^1.6.3",
|
||||||
|
"mikehaertl/php-tmpfile": "^1.1.0",
|
||||||
|
"php": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": ">4.0 <9.4"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"mikehaertl\\pdftk\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Michael Haertl",
|
||||||
|
"email": "haertl.mike@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A PDF conversion and form utility based on pdftk.",
|
||||||
|
"keywords": [
|
||||||
|
"pdf",
|
||||||
|
"pdftk"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/mikehaertl/php-pdftk/issues",
|
||||||
|
"source": "https://github.com/mikehaertl/php-pdftk/tree/0.13.1"
|
||||||
|
},
|
||||||
|
"time": "2023-11-03T16:06:08+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mikehaertl/php-shellcommand",
|
||||||
|
"version": "1.7.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/mikehaertl/php-shellcommand.git",
|
||||||
|
"reference": "e79ea528be155ffdec6f3bf1a4a46307bb49e545"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/mikehaertl/php-shellcommand/zipball/e79ea528be155ffdec6f3bf1a4a46307bb49e545",
|
||||||
|
"reference": "e79ea528be155ffdec6f3bf1a4a46307bb49e545",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">= 5.3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": ">4.0 <=9.4"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"mikehaertl\\shellcommand\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Michael Härtl",
|
||||||
|
"email": "haertl.mike@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "An object oriented interface to shell commands",
|
||||||
|
"keywords": [
|
||||||
|
"shell"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/mikehaertl/php-shellcommand/issues",
|
||||||
|
"source": "https://github.com/mikehaertl/php-shellcommand/tree/1.7.0"
|
||||||
|
},
|
||||||
|
"time": "2023-04-19T08:25:22+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mikehaertl/php-tmpfile",
|
||||||
|
"version": "1.2.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/mikehaertl/php-tmpfile.git",
|
||||||
|
"reference": "70a5b70b17bc0d9666388e6a551ecc93d0b40a10"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/mikehaertl/php-tmpfile/zipball/70a5b70b17bc0d9666388e6a551ecc93d0b40a10",
|
||||||
|
"reference": "70a5b70b17bc0d9666388e6a551ecc93d0b40a10",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"php": ">=5.3.0",
|
||||||
|
"phpunit/phpunit": ">4.0 <=9.4"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"mikehaertl\\tmp\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Michael Härtl",
|
||||||
|
"email": "haertl.mike@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A convenience class for temporary files",
|
||||||
|
"keywords": [
|
||||||
|
"files"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/mikehaertl/php-tmpfile/issues",
|
||||||
|
"source": "https://github.com/mikehaertl/php-tmpfile/tree/1.2.1"
|
||||||
|
},
|
||||||
|
"time": "2021-03-01T18:26:25+00:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
|
|
@ -14,5 +154,5 @@
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": [],
|
"platform": [],
|
||||||
"platform-dev": [],
|
"platform-dev": [],
|
||||||
"plugin-api-version": "2.3.0"
|
"plugin-api-version": "2.6.0"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,35 +45,34 @@ class ClassLoader
|
||||||
/** @var \Closure(string):void */
|
/** @var \Closure(string):void */
|
||||||
private static $includeFile;
|
private static $includeFile;
|
||||||
|
|
||||||
/** @var ?string */
|
/** @var string|null */
|
||||||
private $vendorDir;
|
private $vendorDir;
|
||||||
|
|
||||||
// PSR-4
|
// PSR-4
|
||||||
/**
|
/**
|
||||||
* @var array[]
|
* @var array<string, array<string, int>>
|
||||||
* @psalm-var array<string, array<string, int>>
|
|
||||||
*/
|
*/
|
||||||
private $prefixLengthsPsr4 = array();
|
private $prefixLengthsPsr4 = array();
|
||||||
/**
|
/**
|
||||||
* @var array[]
|
* @var array<string, list<string>>
|
||||||
* @psalm-var array<string, array<int, string>>
|
|
||||||
*/
|
*/
|
||||||
private $prefixDirsPsr4 = array();
|
private $prefixDirsPsr4 = array();
|
||||||
/**
|
/**
|
||||||
* @var array[]
|
* @var list<string>
|
||||||
* @psalm-var array<string, string>
|
|
||||||
*/
|
*/
|
||||||
private $fallbackDirsPsr4 = array();
|
private $fallbackDirsPsr4 = array();
|
||||||
|
|
||||||
// PSR-0
|
// PSR-0
|
||||||
/**
|
/**
|
||||||
* @var array[]
|
* List of PSR-0 prefixes
|
||||||
* @psalm-var array<string, array<string, string[]>>
|
*
|
||||||
|
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||||
|
*
|
||||||
|
* @var array<string, array<string, list<string>>>
|
||||||
*/
|
*/
|
||||||
private $prefixesPsr0 = array();
|
private $prefixesPsr0 = array();
|
||||||
/**
|
/**
|
||||||
* @var array[]
|
* @var list<string>
|
||||||
* @psalm-var array<string, string>
|
|
||||||
*/
|
*/
|
||||||
private $fallbackDirsPsr0 = array();
|
private $fallbackDirsPsr0 = array();
|
||||||
|
|
||||||
|
|
@ -81,8 +80,7 @@ class ClassLoader
|
||||||
private $useIncludePath = false;
|
private $useIncludePath = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var array<string, string>
|
||||||
* @psalm-var array<string, string>
|
|
||||||
*/
|
*/
|
||||||
private $classMap = array();
|
private $classMap = array();
|
||||||
|
|
||||||
|
|
@ -90,21 +88,20 @@ class ClassLoader
|
||||||
private $classMapAuthoritative = false;
|
private $classMapAuthoritative = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool[]
|
* @var array<string, bool>
|
||||||
* @psalm-var array<string, bool>
|
|
||||||
*/
|
*/
|
||||||
private $missingClasses = array();
|
private $missingClasses = array();
|
||||||
|
|
||||||
/** @var ?string */
|
/** @var string|null */
|
||||||
private $apcuPrefix;
|
private $apcuPrefix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var self[]
|
* @var array<string, self>
|
||||||
*/
|
*/
|
||||||
private static $registeredLoaders = array();
|
private static $registeredLoaders = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ?string $vendorDir
|
* @param string|null $vendorDir
|
||||||
*/
|
*/
|
||||||
public function __construct($vendorDir = null)
|
public function __construct($vendorDir = null)
|
||||||
{
|
{
|
||||||
|
|
@ -113,7 +110,7 @@ class ClassLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string[]
|
* @return array<string, list<string>>
|
||||||
*/
|
*/
|
||||||
public function getPrefixes()
|
public function getPrefixes()
|
||||||
{
|
{
|
||||||
|
|
@ -125,8 +122,7 @@ class ClassLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array[]
|
* @return array<string, list<string>>
|
||||||
* @psalm-return array<string, array<int, string>>
|
|
||||||
*/
|
*/
|
||||||
public function getPrefixesPsr4()
|
public function getPrefixesPsr4()
|
||||||
{
|
{
|
||||||
|
|
@ -134,8 +130,7 @@ class ClassLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array[]
|
* @return list<string>
|
||||||
* @psalm-return array<string, string>
|
|
||||||
*/
|
*/
|
||||||
public function getFallbackDirs()
|
public function getFallbackDirs()
|
||||||
{
|
{
|
||||||
|
|
@ -143,8 +138,7 @@ class ClassLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array[]
|
* @return list<string>
|
||||||
* @psalm-return array<string, string>
|
|
||||||
*/
|
*/
|
||||||
public function getFallbackDirsPsr4()
|
public function getFallbackDirsPsr4()
|
||||||
{
|
{
|
||||||
|
|
@ -152,8 +146,7 @@ class ClassLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string[] Array of classname => path
|
* @return array<string, string> Array of classname => path
|
||||||
* @psalm-return array<string, string>
|
|
||||||
*/
|
*/
|
||||||
public function getClassMap()
|
public function getClassMap()
|
||||||
{
|
{
|
||||||
|
|
@ -161,8 +154,7 @@ class ClassLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string[] $classMap Class to filename map
|
* @param array<string, string> $classMap Class to filename map
|
||||||
* @psalm-param array<string, string> $classMap
|
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|
@ -179,24 +171,25 @@ class ClassLoader
|
||||||
* Registers a set of PSR-0 directories for a given prefix, either
|
* Registers a set of PSR-0 directories for a given prefix, either
|
||||||
* appending or prepending to the ones previously set for this prefix.
|
* appending or prepending to the ones previously set for this prefix.
|
||||||
*
|
*
|
||||||
* @param string $prefix The prefix
|
* @param string $prefix The prefix
|
||||||
* @param string[]|string $paths The PSR-0 root directories
|
* @param list<string>|string $paths The PSR-0 root directories
|
||||||
* @param bool $prepend Whether to prepend the directories
|
* @param bool $prepend Whether to prepend the directories
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function add($prefix, $paths, $prepend = false)
|
public function add($prefix, $paths, $prepend = false)
|
||||||
{
|
{
|
||||||
|
$paths = (array) $paths;
|
||||||
if (!$prefix) {
|
if (!$prefix) {
|
||||||
if ($prepend) {
|
if ($prepend) {
|
||||||
$this->fallbackDirsPsr0 = array_merge(
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
(array) $paths,
|
$paths,
|
||||||
$this->fallbackDirsPsr0
|
$this->fallbackDirsPsr0
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$this->fallbackDirsPsr0 = array_merge(
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
$this->fallbackDirsPsr0,
|
$this->fallbackDirsPsr0,
|
||||||
(array) $paths
|
$paths
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,19 +198,19 @@ class ClassLoader
|
||||||
|
|
||||||
$first = $prefix[0];
|
$first = $prefix[0];
|
||||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||||
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($prepend) {
|
if ($prepend) {
|
||||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
(array) $paths,
|
$paths,
|
||||||
$this->prefixesPsr0[$first][$prefix]
|
$this->prefixesPsr0[$first][$prefix]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
$this->prefixesPsr0[$first][$prefix],
|
$this->prefixesPsr0[$first][$prefix],
|
||||||
(array) $paths
|
$paths
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -226,9 +219,9 @@ class ClassLoader
|
||||||
* Registers a set of PSR-4 directories for a given namespace, either
|
* Registers a set of PSR-4 directories for a given namespace, either
|
||||||
* appending or prepending to the ones previously set for this namespace.
|
* appending or prepending to the ones previously set for this namespace.
|
||||||
*
|
*
|
||||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
* @param string[]|string $paths The PSR-4 base directories
|
* @param list<string>|string $paths The PSR-4 base directories
|
||||||
* @param bool $prepend Whether to prepend the directories
|
* @param bool $prepend Whether to prepend the directories
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*
|
*
|
||||||
|
|
@ -236,17 +229,18 @@ class ClassLoader
|
||||||
*/
|
*/
|
||||||
public function addPsr4($prefix, $paths, $prepend = false)
|
public function addPsr4($prefix, $paths, $prepend = false)
|
||||||
{
|
{
|
||||||
|
$paths = (array) $paths;
|
||||||
if (!$prefix) {
|
if (!$prefix) {
|
||||||
// Register directories for the root namespace.
|
// Register directories for the root namespace.
|
||||||
if ($prepend) {
|
if ($prepend) {
|
||||||
$this->fallbackDirsPsr4 = array_merge(
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
(array) $paths,
|
$paths,
|
||||||
$this->fallbackDirsPsr4
|
$this->fallbackDirsPsr4
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$this->fallbackDirsPsr4 = array_merge(
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
$this->fallbackDirsPsr4,
|
$this->fallbackDirsPsr4,
|
||||||
(array) $paths
|
$paths
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||||
|
|
@ -256,18 +250,18 @@ class ClassLoader
|
||||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
}
|
}
|
||||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||||
} elseif ($prepend) {
|
} elseif ($prepend) {
|
||||||
// Prepend directories for an already registered namespace.
|
// Prepend directories for an already registered namespace.
|
||||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
(array) $paths,
|
$paths,
|
||||||
$this->prefixDirsPsr4[$prefix]
|
$this->prefixDirsPsr4[$prefix]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Append directories for an already registered namespace.
|
// Append directories for an already registered namespace.
|
||||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
$this->prefixDirsPsr4[$prefix],
|
$this->prefixDirsPsr4[$prefix],
|
||||||
(array) $paths
|
$paths
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -276,8 +270,8 @@ class ClassLoader
|
||||||
* Registers a set of PSR-0 directories for a given prefix,
|
* Registers a set of PSR-0 directories for a given prefix,
|
||||||
* replacing any others previously set for this prefix.
|
* replacing any others previously set for this prefix.
|
||||||
*
|
*
|
||||||
* @param string $prefix The prefix
|
* @param string $prefix The prefix
|
||||||
* @param string[]|string $paths The PSR-0 base directories
|
* @param list<string>|string $paths The PSR-0 base directories
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|
@ -294,8 +288,8 @@ class ClassLoader
|
||||||
* Registers a set of PSR-4 directories for a given namespace,
|
* Registers a set of PSR-4 directories for a given namespace,
|
||||||
* replacing any others previously set for this namespace.
|
* replacing any others previously set for this namespace.
|
||||||
*
|
*
|
||||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
* @param string[]|string $paths The PSR-4 base directories
|
* @param list<string>|string $paths The PSR-4 base directories
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*
|
*
|
||||||
|
|
@ -481,9 +475,9 @@ class ClassLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||||
*
|
*
|
||||||
* @return self[]
|
* @return array<string, self>
|
||||||
*/
|
*/
|
||||||
public static function getRegisteredLoaders()
|
public static function getRegisteredLoaders()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -77,8 +77,8 @@ return array(
|
||||||
'OCA\\Richdocuments\\Service\\FileTargetService' => $baseDir . '/../lib/Service/FileTargetService.php',
|
'OCA\\Richdocuments\\Service\\FileTargetService' => $baseDir . '/../lib/Service/FileTargetService.php',
|
||||||
'OCA\\Richdocuments\\Service\\FontService' => $baseDir . '/../lib/Service/FontService.php',
|
'OCA\\Richdocuments\\Service\\FontService' => $baseDir . '/../lib/Service/FontService.php',
|
||||||
'OCA\\Richdocuments\\Service\\InitialStateService' => $baseDir . '/../lib/Service/InitialStateService.php',
|
'OCA\\Richdocuments\\Service\\InitialStateService' => $baseDir . '/../lib/Service/InitialStateService.php',
|
||||||
'OCA\\Richdocuments\\Service\\RemoteOptionsService' => $baseDir . '/../lib/Service/RemoteOptionsService.php',
|
|
||||||
'OCA\\Richdocuments\\Service\\PdfService' => $baseDir . '/../lib/Service/PdfService.php',
|
'OCA\\Richdocuments\\Service\\PdfService' => $baseDir . '/../lib/Service/PdfService.php',
|
||||||
|
'OCA\\Richdocuments\\Service\\RemoteOptionsService' => $baseDir . '/../lib/Service/RemoteOptionsService.php',
|
||||||
'OCA\\Richdocuments\\Service\\RemoteService' => $baseDir . '/../lib/Service/RemoteService.php',
|
'OCA\\Richdocuments\\Service\\RemoteService' => $baseDir . '/../lib/Service/RemoteService.php',
|
||||||
'OCA\\Richdocuments\\Service\\TemplateFieldService' => $baseDir . '/../lib/Service/TemplateFieldService.php',
|
'OCA\\Richdocuments\\Service\\TemplateFieldService' => $baseDir . '/../lib/Service/TemplateFieldService.php',
|
||||||
'OCA\\Richdocuments\\Service\\UserScopeService' => $baseDir . '/../lib/Service/UserScopeService.php',
|
'OCA\\Richdocuments\\Service\\UserScopeService' => $baseDir . '/../lib/Service/UserScopeService.php',
|
||||||
|
|
@ -90,12 +90,13 @@ return array(
|
||||||
'OCA\\Richdocuments\\TokenManager' => $baseDir . '/../lib/TokenManager.php',
|
'OCA\\Richdocuments\\TokenManager' => $baseDir . '/../lib/TokenManager.php',
|
||||||
'OCA\\Richdocuments\\UploadException' => $baseDir . '/../lib/UploadException.php',
|
'OCA\\Richdocuments\\UploadException' => $baseDir . '/../lib/UploadException.php',
|
||||||
'OCA\\Richdocuments\\WOPI\\Parser' => $baseDir . '/../lib/WOPI/Parser.php',
|
'OCA\\Richdocuments\\WOPI\\Parser' => $baseDir . '/../lib/WOPI/Parser.php',
|
||||||
'mikehaertl\\pdftk\\Command' => $baseDir . '/../vendor/mikehaertl/php-pdftk/src/Command.php',
|
'mikehaertl\\pdftk\\Command' => $vendorDir . '/mikehaertl/php-pdftk/src/Command.php',
|
||||||
'mikehaertl\\pdftk\\DataFields' => $baseDir . '/../vendor/mikehaertl/php-pdftk/src/DataFields.php',
|
'mikehaertl\\pdftk\\DataFields' => $vendorDir . '/mikehaertl/php-pdftk/src/DataFields.php',
|
||||||
'mikehaertl\\pdftk\\FdfFile' => $baseDir . '/../vendor/mikehaertl/php-pdftk/src/FdfFile.php',
|
'mikehaertl\\pdftk\\FdfFile' => $vendorDir . '/mikehaertl/php-pdftk/src/FdfFile.php',
|
||||||
'mikehaertl\\pdftk\\InfoFields' => $baseDir . '/../vendor/mikehaertl/php-pdftk/src/InfoFields.php',
|
'mikehaertl\\pdftk\\InfoFields' => $vendorDir . '/mikehaertl/php-pdftk/src/InfoFields.php',
|
||||||
'mikehaertl\\pdftk\\InfoFile' => $baseDir . '/../vendor/mikehaertl/php-pdftk/src/InfoFile.php',
|
'mikehaertl\\pdftk\\InfoFile' => $vendorDir . '/mikehaertl/php-pdftk/src/InfoFile.php',
|
||||||
'mikehaertl\\pdftk\\Pdf' => $baseDir . '/../vendor/mikehaertl/php-pdftk/src/Pdf.php',
|
'mikehaertl\\pdftk\\Pdf' => $vendorDir . '/mikehaertl/php-pdftk/src/Pdf.php',
|
||||||
'mikehaertl\\pdftk\\XfdfFile' => $baseDir . '/../vendor/mikehaertl/php-pdftk/src/XfdfFile.php',
|
'mikehaertl\\pdftk\\XfdfFile' => $vendorDir . '/mikehaertl/php-pdftk/src/XfdfFile.php',
|
||||||
'mikehaertl\\shellcommand\\Command' => $baseDir . '/../vendor/mikehaertl/php-shellcommand/src/Command.php',
|
'mikehaertl\\shellcommand\\Command' => $vendorDir . '/mikehaertl/php-shellcommand/src/Command.php',
|
||||||
|
'mikehaertl\\tmp\\File' => $vendorDir . '/mikehaertl/php-tmpfile/src/File.php',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ $vendorDir = dirname(__DIR__);
|
||||||
$baseDir = $vendorDir;
|
$baseDir = $vendorDir;
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'mikehaertl\\shellcommand\\' => array($baseDir . '/../vendor/mikehaertl/php-shellcommand/src'),
|
'mikehaertl\\tmp\\' => array($vendorDir . '/mikehaertl/php-tmpfile/src'),
|
||||||
'mikehaertl\\pdftk\\' => array($baseDir . '/../vendor/mikehaertl/php-pdftk/src'),
|
'mikehaertl\\shellcommand\\' => array($vendorDir . '/mikehaertl/php-shellcommand/src'),
|
||||||
|
'mikehaertl\\pdftk\\' => array($vendorDir . '/mikehaertl/php-pdftk/src'),
|
||||||
'OCA\\Richdocuments\\' => array($baseDir . '/../lib'),
|
'OCA\\Richdocuments\\' => array($baseDir . '/../lib'),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ class ComposerAutoloaderInitRichdocuments
|
||||||
return self::$loader;
|
return self::$loader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require __DIR__ . '/platform_check.php';
|
||||||
|
|
||||||
spl_autoload_register(array('ComposerAutoloaderInitRichdocuments', 'loadClassLoader'), true, true);
|
spl_autoload_register(array('ComposerAutoloaderInitRichdocuments', 'loadClassLoader'), true, true);
|
||||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||||
spl_autoload_unregister(array('ComposerAutoloaderInitRichdocuments', 'loadClassLoader'));
|
spl_autoload_unregister(array('ComposerAutoloaderInitRichdocuments', 'loadClassLoader'));
|
||||||
|
|
|
||||||
|
|
@ -7,27 +7,32 @@ namespace Composer\Autoload;
|
||||||
class ComposerStaticInitRichdocuments
|
class ComposerStaticInitRichdocuments
|
||||||
{
|
{
|
||||||
public static $prefixLengthsPsr4 = array (
|
public static $prefixLengthsPsr4 = array (
|
||||||
'm' =>
|
'm' =>
|
||||||
array (
|
array (
|
||||||
|
'mikehaertl\\tmp\\' => 15,
|
||||||
'mikehaertl\\shellcommand\\' => 24,
|
'mikehaertl\\shellcommand\\' => 24,
|
||||||
'mikehaertl\\pdftk\\' => 17,
|
'mikehaertl\\pdftk\\' => 17,
|
||||||
),
|
),
|
||||||
'O' =>
|
'O' =>
|
||||||
array (
|
array (
|
||||||
'OCA\\Richdocuments\\' => 18,
|
'OCA\\Richdocuments\\' => 18,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
public static $prefixDirsPsr4 = array (
|
public static $prefixDirsPsr4 = array (
|
||||||
'mikehaertl\\shellcommand\\' =>
|
'mikehaertl\\tmp\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/../vendor/mikehaertl/php-shellcommand/src',
|
0 => __DIR__ . '/..' . '/mikehaertl/php-tmpfile/src',
|
||||||
),
|
),
|
||||||
'mikehaertl\\pdftk\\' =>
|
'mikehaertl\\shellcommand\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/../vendor/mikehaertl/php-pdftk/src',
|
0 => __DIR__ . '/..' . '/mikehaertl/php-shellcommand/src',
|
||||||
),
|
),
|
||||||
'OCA\\Richdocuments\\' =>
|
'mikehaertl\\pdftk\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/mikehaertl/php-pdftk/src',
|
||||||
|
),
|
||||||
|
'OCA\\Richdocuments\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/../lib',
|
0 => __DIR__ . '/..' . '/../lib',
|
||||||
),
|
),
|
||||||
|
|
@ -105,8 +110,8 @@ class ComposerStaticInitRichdocuments
|
||||||
'OCA\\Richdocuments\\Service\\FileTargetService' => __DIR__ . '/..' . '/../lib/Service/FileTargetService.php',
|
'OCA\\Richdocuments\\Service\\FileTargetService' => __DIR__ . '/..' . '/../lib/Service/FileTargetService.php',
|
||||||
'OCA\\Richdocuments\\Service\\FontService' => __DIR__ . '/..' . '/../lib/Service/FontService.php',
|
'OCA\\Richdocuments\\Service\\FontService' => __DIR__ . '/..' . '/../lib/Service/FontService.php',
|
||||||
'OCA\\Richdocuments\\Service\\InitialStateService' => __DIR__ . '/..' . '/../lib/Service/InitialStateService.php',
|
'OCA\\Richdocuments\\Service\\InitialStateService' => __DIR__ . '/..' . '/../lib/Service/InitialStateService.php',
|
||||||
'OCA\\Richdocuments\\Service\\RemoteOptionsService' => __DIR__ . '/..' . '/../lib/Service/RemoteOptionsService.php',
|
|
||||||
'OCA\\Richdocuments\\Service\\PdfService' => __DIR__ . '/..' . '/../lib/Service/PdfService.php',
|
'OCA\\Richdocuments\\Service\\PdfService' => __DIR__ . '/..' . '/../lib/Service/PdfService.php',
|
||||||
|
'OCA\\Richdocuments\\Service\\RemoteOptionsService' => __DIR__ . '/..' . '/../lib/Service/RemoteOptionsService.php',
|
||||||
'OCA\\Richdocuments\\Service\\RemoteService' => __DIR__ . '/..' . '/../lib/Service/RemoteService.php',
|
'OCA\\Richdocuments\\Service\\RemoteService' => __DIR__ . '/..' . '/../lib/Service/RemoteService.php',
|
||||||
'OCA\\Richdocuments\\Service\\TemplateFieldService' => __DIR__ . '/..' . '/../lib/Service/TemplateFieldService.php',
|
'OCA\\Richdocuments\\Service\\TemplateFieldService' => __DIR__ . '/..' . '/../lib/Service/TemplateFieldService.php',
|
||||||
'OCA\\Richdocuments\\Service\\UserScopeService' => __DIR__ . '/..' . '/../lib/Service/UserScopeService.php',
|
'OCA\\Richdocuments\\Service\\UserScopeService' => __DIR__ . '/..' . '/../lib/Service/UserScopeService.php',
|
||||||
|
|
@ -118,14 +123,15 @@ class ComposerStaticInitRichdocuments
|
||||||
'OCA\\Richdocuments\\TokenManager' => __DIR__ . '/..' . '/../lib/TokenManager.php',
|
'OCA\\Richdocuments\\TokenManager' => __DIR__ . '/..' . '/../lib/TokenManager.php',
|
||||||
'OCA\\Richdocuments\\UploadException' => __DIR__ . '/..' . '/../lib/UploadException.php',
|
'OCA\\Richdocuments\\UploadException' => __DIR__ . '/..' . '/../lib/UploadException.php',
|
||||||
'OCA\\Richdocuments\\WOPI\\Parser' => __DIR__ . '/..' . '/../lib/WOPI/Parser.php',
|
'OCA\\Richdocuments\\WOPI\\Parser' => __DIR__ . '/..' . '/../lib/WOPI/Parser.php',
|
||||||
'mikehaertl\\pdftk\\Command' => __DIR__ . '/..' . '/../vendor/mikehaertl/php-pdftk/src/Command.php',
|
'mikehaertl\\pdftk\\Command' => __DIR__ . '/..' . '/mikehaertl/php-pdftk/src/Command.php',
|
||||||
'mikehaertl\\pdftk\\DataFields' => __DIR__ . '/..' . '/../vendor/mikehaertl/php-pdftk/src/DataFields.php',
|
'mikehaertl\\pdftk\\DataFields' => __DIR__ . '/..' . '/mikehaertl/php-pdftk/src/DataFields.php',
|
||||||
'mikehaertl\\pdftk\\FdfFile' => __DIR__ . '/..' . '/../vendor/mikehaertl/php-pdftk/src/FdfFile.php',
|
'mikehaertl\\pdftk\\FdfFile' => __DIR__ . '/..' . '/mikehaertl/php-pdftk/src/FdfFile.php',
|
||||||
'mikehaertl\\pdftk\\InfoFields' => __DIR__ . '/..' . '/../vendor/mikehaertl/php-pdftk/src/InfoFields.php',
|
'mikehaertl\\pdftk\\InfoFields' => __DIR__ . '/..' . '/mikehaertl/php-pdftk/src/InfoFields.php',
|
||||||
'mikehaertl\\pdftk\\InfoFile' => __DIR__ . '/..' . '/../vendor/mikehaertl/php-pdftk/src/InfoFile.php',
|
'mikehaertl\\pdftk\\InfoFile' => __DIR__ . '/..' . '/mikehaertl/php-pdftk/src/InfoFile.php',
|
||||||
'mikehaertl\\pdftk\\Pdf' => __DIR__ . '/..' . '/../vendor/mikehaertl/php-pdftk/src/Pdf.php',
|
'mikehaertl\\pdftk\\Pdf' => __DIR__ . '/..' . '/mikehaertl/php-pdftk/src/Pdf.php',
|
||||||
'mikehaertl\\pdftk\\XfdfFile' => __DIR__ . '/..' . '/../vendor/mikehaertl/php-pdftk/src/XfdfFile.php',
|
'mikehaertl\\pdftk\\XfdfFile' => __DIR__ . '/..' . '/mikehaertl/php-pdftk/src/XfdfFile.php',
|
||||||
'mikehaertl\\shellcommand\\Command' => __DIR__ . '/..' . '/../vendor/mikehaertl/php-shellcommand/src/Command.php',
|
'mikehaertl\\shellcommand\\Command' => __DIR__ . '/..' . '/mikehaertl/php-shellcommand/src/Command.php',
|
||||||
|
'mikehaertl\\tmp\\File' => __DIR__ . '/..' . '/mikehaertl/php-tmpfile/src/File.php',
|
||||||
);
|
);
|
||||||
|
|
||||||
public static function getInitializer(ClassLoader $loader)
|
public static function getInitializer(ClassLoader $loader)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,154 @@
|
||||||
{
|
{
|
||||||
"packages": [],
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "mikehaertl/php-pdftk",
|
||||||
|
"version": "0.13.1",
|
||||||
|
"version_normalized": "0.13.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/mikehaertl/php-pdftk.git",
|
||||||
|
"reference": "3851b08c1027489e48387d7c14c27bc295d98239"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/mikehaertl/php-pdftk/zipball/3851b08c1027489e48387d7c14c27bc295d98239",
|
||||||
|
"reference": "3851b08c1027489e48387d7c14c27bc295d98239",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"mikehaertl/php-shellcommand": "^1.6.3",
|
||||||
|
"mikehaertl/php-tmpfile": "^1.1.0",
|
||||||
|
"php": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": ">4.0 <9.4"
|
||||||
|
},
|
||||||
|
"time": "2023-11-03T16:06:08+00:00",
|
||||||
|
"type": "library",
|
||||||
|
"installation-source": "dist",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"mikehaertl\\pdftk\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Michael Haertl",
|
||||||
|
"email": "haertl.mike@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A PDF conversion and form utility based on pdftk.",
|
||||||
|
"keywords": [
|
||||||
|
"pdf",
|
||||||
|
"pdftk"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/mikehaertl/php-pdftk/issues",
|
||||||
|
"source": "https://github.com/mikehaertl/php-pdftk/tree/0.13.1"
|
||||||
|
},
|
||||||
|
"install-path": "../mikehaertl/php-pdftk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mikehaertl/php-shellcommand",
|
||||||
|
"version": "1.7.0",
|
||||||
|
"version_normalized": "1.7.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/mikehaertl/php-shellcommand.git",
|
||||||
|
"reference": "e79ea528be155ffdec6f3bf1a4a46307bb49e545"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/mikehaertl/php-shellcommand/zipball/e79ea528be155ffdec6f3bf1a4a46307bb49e545",
|
||||||
|
"reference": "e79ea528be155ffdec6f3bf1a4a46307bb49e545",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">= 5.3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": ">4.0 <=9.4"
|
||||||
|
},
|
||||||
|
"time": "2023-04-19T08:25:22+00:00",
|
||||||
|
"type": "library",
|
||||||
|
"installation-source": "dist",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"mikehaertl\\shellcommand\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Michael Härtl",
|
||||||
|
"email": "haertl.mike@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "An object oriented interface to shell commands",
|
||||||
|
"keywords": [
|
||||||
|
"shell"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/mikehaertl/php-shellcommand/issues",
|
||||||
|
"source": "https://github.com/mikehaertl/php-shellcommand/tree/1.7.0"
|
||||||
|
},
|
||||||
|
"install-path": "../mikehaertl/php-shellcommand"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mikehaertl/php-tmpfile",
|
||||||
|
"version": "1.2.1",
|
||||||
|
"version_normalized": "1.2.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/mikehaertl/php-tmpfile.git",
|
||||||
|
"reference": "70a5b70b17bc0d9666388e6a551ecc93d0b40a10"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/mikehaertl/php-tmpfile/zipball/70a5b70b17bc0d9666388e6a551ecc93d0b40a10",
|
||||||
|
"reference": "70a5b70b17bc0d9666388e6a551ecc93d0b40a10",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"php": ">=5.3.0",
|
||||||
|
"phpunit/phpunit": ">4.0 <=9.4"
|
||||||
|
},
|
||||||
|
"time": "2021-03-01T18:26:25+00:00",
|
||||||
|
"type": "library",
|
||||||
|
"installation-source": "dist",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"mikehaertl\\tmp\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Michael Härtl",
|
||||||
|
"email": "haertl.mike@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A convenience class for temporary files",
|
||||||
|
"keywords": [
|
||||||
|
"files"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/mikehaertl/php-tmpfile/issues",
|
||||||
|
"source": "https://github.com/mikehaertl/php-tmpfile/tree/1.2.1"
|
||||||
|
},
|
||||||
|
"install-path": "../mikehaertl/php-tmpfile"
|
||||||
|
}
|
||||||
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dev-package-names": []
|
"dev-package-names": []
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
'name' => '__root__',
|
'name' => '__root__',
|
||||||
'pretty_version' => 'dev-main',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => 'dev-main',
|
'version' => 'dev-main',
|
||||||
'reference' => '54ab2a0b624b592f982ea341fe730e24dfbc4a8c',
|
'reference' => '88eb9d7b4bbe5f42df84e9ed12183e91554e0a1d',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../',
|
'install_path' => __DIR__ . '/../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
|
|
@ -13,11 +13,38 @@
|
||||||
'__root__' => array(
|
'__root__' => array(
|
||||||
'pretty_version' => 'dev-main',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => 'dev-main',
|
'version' => 'dev-main',
|
||||||
'reference' => '54ab2a0b624b592f982ea341fe730e24dfbc4a8c',
|
'reference' => '88eb9d7b4bbe5f42df84e9ed12183e91554e0a1d',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../',
|
'install_path' => __DIR__ . '/../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
|
'mikehaertl/php-pdftk' => array(
|
||||||
|
'pretty_version' => '0.13.1',
|
||||||
|
'version' => '0.13.1.0',
|
||||||
|
'reference' => '3851b08c1027489e48387d7c14c27bc295d98239',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../mikehaertl/php-pdftk',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'mikehaertl/php-shellcommand' => array(
|
||||||
|
'pretty_version' => '1.7.0',
|
||||||
|
'version' => '1.7.0.0',
|
||||||
|
'reference' => 'e79ea528be155ffdec6f3bf1a4a46307bb49e545',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../mikehaertl/php-shellcommand',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'mikehaertl/php-tmpfile' => array(
|
||||||
|
'pretty_version' => '1.2.1',
|
||||||
|
'version' => '1.2.1.0',
|
||||||
|
'reference' => '70a5b70b17bc0d9666388e6a551ecc93d0b40a10',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../mikehaertl/php-tmpfile',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
26
composer/composer/platform_check.php
Normal file
26
composer/composer/platform_check.php
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// platform_check.php @generated by Composer
|
||||||
|
|
||||||
|
$issues = array();
|
||||||
|
|
||||||
|
if (!(PHP_VERSION_ID >= 50300)) {
|
||||||
|
$issues[] = 'Your Composer dependencies require a PHP version ">= 5.3.0". You are running ' . PHP_VERSION . '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($issues) {
|
||||||
|
if (!headers_sent()) {
|
||||||
|
header('HTTP/1.1 500 Internal Server Error');
|
||||||
|
}
|
||||||
|
if (!ini_get('display_errors')) {
|
||||||
|
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||||
|
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||||
|
} elseif (!headers_sent()) {
|
||||||
|
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trigger_error(
|
||||||
|
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||||
|
E_USER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
55
composer/mikehaertl/php-pdftk/.github/workflows/tests.yml
vendored
Normal file
55
composer/mikehaertl/php-pdftk/.github/workflows/tests.yml
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
name: Tests
|
||||||
|
on: pull_request
|
||||||
|
jobs:
|
||||||
|
phpunit:
|
||||||
|
name: PHP ${{ matrix.php }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
php:
|
||||||
|
- "5.3"
|
||||||
|
- "5.4"
|
||||||
|
- "5.5"
|
||||||
|
- "5.6"
|
||||||
|
- "7.0"
|
||||||
|
- "7.1"
|
||||||
|
- "7.2"
|
||||||
|
- "7.3"
|
||||||
|
- "7.4"
|
||||||
|
- "8.0"
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install pdftk
|
||||||
|
run: |
|
||||||
|
cd /tmp
|
||||||
|
sudo wget http://mirrors.kernel.org/ubuntu/pool/universe/p/pdftk-java/pdftk-java_3.0.9-1_all.deb
|
||||||
|
sudo apt install -y -q ./pdftk-java_3.0.9-1_all.deb
|
||||||
|
pdftk --version
|
||||||
|
|
||||||
|
- name: Install PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php }}
|
||||||
|
tools: composer:v2
|
||||||
|
|
||||||
|
- name: Update composer
|
||||||
|
run: composer self-update
|
||||||
|
|
||||||
|
- name: Get composer cache directory
|
||||||
|
id: composer-cache
|
||||||
|
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||||
|
|
||||||
|
- name: Cache composer cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ${{ steps.composer-cache.outputs.dir }}
|
||||||
|
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
|
||||||
|
restore-keys: ${{ runner.os }}-composer-
|
||||||
|
|
||||||
|
- name: Install composer packages
|
||||||
|
run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
|
||||||
|
|
||||||
|
- name: Run phpunit
|
||||||
|
run: vendor/bin/phpunit --color=always
|
||||||
21
composer/mikehaertl/php-pdftk/LICENSE
Normal file
21
composer/mikehaertl/php-pdftk/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Michael Härtl
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
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.
|
||||||
501
composer/mikehaertl/php-pdftk/README.md
Normal file
501
composer/mikehaertl/php-pdftk/README.md
Normal file
|
|
@ -0,0 +1,501 @@
|
||||||
|
php-pdftk
|
||||||
|
=========
|
||||||
|
|
||||||
|
[](https://github.com/mikehaertl/php-pdftk/actions)
|
||||||
|
[](https://packagist.org/packages/mikehaertl/php-pdftk)
|
||||||
|
[](https://packagist.org/packages/mikehaertl/php-pdftk)
|
||||||
|
[](https://github.com/mikehaertl/php-pdftk/blob/master/LICENSE)
|
||||||
|
[](https://packagist.org/packages/mikehaertl/php-pdftk)
|
||||||
|
|
||||||
|
A PDF conversion and form utility based on pdftk.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
*php-pdftk* brings the full power of `pdftk` to PHP - and more.
|
||||||
|
|
||||||
|
* Fill forms, either from a XFDF/FDF file or from a data array (UTF-8 safe for unflattened forms, requires pdftk 2.x !)
|
||||||
|
* Create XFDF or FDF files from PHP arrays (UTF-8 safe!)
|
||||||
|
* Create FDF files from filled PDF forms
|
||||||
|
* Combine pages from several PDF files into a new PDF file
|
||||||
|
* Split a PDF into one file per page
|
||||||
|
* Add background or overlay PDFs
|
||||||
|
* Read out meta data about PDF and form fields
|
||||||
|
* Set passwords and permissions
|
||||||
|
* Remove passwords
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* The `pdftk` command must be installed and working on your system
|
||||||
|
* This library is written for pdftk 2.x versions. You should be able to use it with pdftk 1.x but not all methods will work there.
|
||||||
|
For details consult the man page of pdftk on your system.
|
||||||
|
* There is a [known issue](https://github.com/mikehaertl/php-pdftk/issues/150)
|
||||||
|
on Ubuntu if you installed the `pdftk` package from snap. This version has
|
||||||
|
no permission to write to the `/tmp` directory. You can either set another
|
||||||
|
temporay directory as described below or use another package. For Ubuntu
|
||||||
|
18.10 there's also a `pdftk-java` package available via apt which should work
|
||||||
|
fine. You can also install this package on Ubuntu 18.04 if you download it
|
||||||
|
manually. Also check [this answer](https://askubuntu.com/a/1028983/175814)
|
||||||
|
on askubuntu.
|
||||||
|
|
||||||
|
> **Note:** The pdftk version from the alternative PPA `ppa:malteworld/ppa` is
|
||||||
|
> no longer available. The author instead now points to his answer on askubuntu
|
||||||
|
> linked above.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
You should use [composer](https://getcomposer.org/) to install this library.
|
||||||
|
|
||||||
|
```
|
||||||
|
composer require mikehaertl/php-pdftk
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Create instance for PDF files
|
||||||
|
|
||||||
|
There are several ways to tell the `Pdf` instance which file(s) it should use.
|
||||||
|
Some files may also require a password or need an alias to be used as a handle
|
||||||
|
in some operations (e.g. cat or shuffle).
|
||||||
|
|
||||||
|
> **Note:** In version 2.x of pdftk a handle can be one or more upper case letters.
|
||||||
|
|
||||||
|
```php
|
||||||
|
// Create an instance for a single file
|
||||||
|
$pdf = new Pdf('/path/to/form.pdf');
|
||||||
|
|
||||||
|
// Alternatively add files later. Handles are autogenerated in this case.
|
||||||
|
$pdf = new Pdf();
|
||||||
|
$pdf->addFile('/path/to/file1.pdf');
|
||||||
|
$pdf->addFile('/path/to/file2.pdf');
|
||||||
|
|
||||||
|
// Add files with own handle
|
||||||
|
$pdf = new Pdf();
|
||||||
|
$pdf->addFile('/path/to/file1.pdf', 'A');
|
||||||
|
$pdf->addFile('/path/to/file2.pdf', 'B');
|
||||||
|
// Add file with handle and password
|
||||||
|
$pdf->addFile('/path/to/file3.pdf', 'C', 'secret*password');
|
||||||
|
|
||||||
|
// Shortcut to pass all files to the constructor
|
||||||
|
$pdf = new Pdf([
|
||||||
|
'A' => ['/path/to/file1.pdf', 'secret*password1'],
|
||||||
|
'B' => ['/path/to/file2.pdf', 'secret*password2'],
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Operations
|
||||||
|
|
||||||
|
Please consult the `pdftk` man page for each operation to find out how each operation works
|
||||||
|
in detail and which options are available.
|
||||||
|
|
||||||
|
For all operations you can either save the PDF locally through `saveAs($name)` or send it to the
|
||||||
|
browser with `send()`. If you pass a filename to `send($name)` the client browser will open a download
|
||||||
|
dialogue whereas without a filename it will usually display the PDF inline.
|
||||||
|
|
||||||
|
**IMPORTANT: You can always only perform *one* of the following operations on a single PDF instance.
|
||||||
|
Below you can find a workaround if you need multiple operations.**
|
||||||
|
|
||||||
|
#### Fill Form
|
||||||
|
|
||||||
|
Fill a PDF form with data from a PHP array or an XFDF/FDF file.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
// Fill form with data array
|
||||||
|
$pdf = new Pdf('/full/path/to/form.pdf');
|
||||||
|
$result = $pdf->fillForm([
|
||||||
|
'name'=>'ÄÜÖ äüö мирано čárka',
|
||||||
|
'nested.name' => 'valX',
|
||||||
|
])
|
||||||
|
->needAppearances()
|
||||||
|
->saveAs('filled.pdf');
|
||||||
|
|
||||||
|
// Always check for errors
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill form from FDF
|
||||||
|
$pdf = new Pdf('form.pdf');
|
||||||
|
$result = $pdf->fillForm('data.xfdf')
|
||||||
|
->saveAs('filled.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** When filling in UTF-8 data, you should always add the `needAppearances()` option.
|
||||||
|
This will make sure, that the PDF reader takes care of using the right fonts for rendering,
|
||||||
|
something that pdftk can't do for you. Also note that `flatten()` doesn't really work well
|
||||||
|
if you have special characters in your data.
|
||||||
|
|
||||||
|
If you use `pdftk-java` >= 3.3.0 and the embedded font does not support UTF-8
|
||||||
|
characters you can also replace it with a local font:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
// Fill form with data array
|
||||||
|
$pdf = new Pdf('/full/path/to/form.pdf');
|
||||||
|
$result = $pdf->fillForm($data)
|
||||||
|
->replacementFont('/usr/share/fonts/dejavu/DejaVuSans.ttf')
|
||||||
|
->saveAs('filled.pdf');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Create a XFDF/FDF file from a PHP array
|
||||||
|
|
||||||
|
This is a bonus feature that is not available from `pdftk`.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\XfdfFile;
|
||||||
|
use mikehaertl\pdftk\FdfFile;
|
||||||
|
|
||||||
|
$xfdf = new XfdfFile(['name' => 'Jürgen мирано']);
|
||||||
|
$xfdf->saveAs('/path/to/data.xfdf');
|
||||||
|
|
||||||
|
$fdf = new FdfFile(['name' => 'Jürgen мирано']);
|
||||||
|
$fdf->saveAs('/path/to/data.fdf');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Cat
|
||||||
|
|
||||||
|
Assemble a PDF from pages from one or more PDF files.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
// Extract pages 1-5 and 7,4,9 into a new file
|
||||||
|
$pdf = new Pdf('/path/to/my.pdf');
|
||||||
|
$result = $pdf->cat(1, 5)
|
||||||
|
->cat([7, 4, 9])
|
||||||
|
->saveAs('/path/to/new.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine pages from several files
|
||||||
|
$pdf = new Pdf([
|
||||||
|
'A' => '/path/file1.pdf', // A is alias for file1.pdf
|
||||||
|
'B' => ['/path/file2.pdf','pass**word'], // B is alias for file2.pdf
|
||||||
|
'C' => ['/path/file3.pdf','secret**pw'], // C is alias for file3.pdf
|
||||||
|
]);
|
||||||
|
$result = $pdf->cat(1, 5, 'A') // pages 1-5 from A
|
||||||
|
->cat(3, null, 'B') // page 3 from B
|
||||||
|
->cat(7, 'end', 'B', null, 'east') // pages 7-end from B, rotated East
|
||||||
|
->cat('end',3,'A','even') // even pages 3-end in reverse order from A
|
||||||
|
->cat([2,3,7], 'C') // pages 2,3 and 7 from C
|
||||||
|
->saveAs('/path/new.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Shuffle
|
||||||
|
|
||||||
|
Like `cat()` but create "*streams*" and fill the new PDF with one page from each
|
||||||
|
stream at a time.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
$pdf = new Pdf([
|
||||||
|
'A' => '/path/file1.pdf', // A is alias for file1.pdf
|
||||||
|
'B' => '/path/file2.pdf', // B is alias for file2.pdf
|
||||||
|
]);
|
||||||
|
|
||||||
|
// new.pdf will have pages A1, B3, A2, B4, A3, B5, ...
|
||||||
|
$result = $pdf->shuffle(1, 5, 'A') // pages 1-5 from A
|
||||||
|
->shuffle(3, 8, 'B') // pages 3-8 from B
|
||||||
|
->saveAs('/path/new.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Burst
|
||||||
|
|
||||||
|
Split a PDF file into one file per page.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
$result = $pdf->burst('/path/page_%d.pdf'); // Supply a printf() pattern
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Add background PDF
|
||||||
|
|
||||||
|
Add another PDF file as background.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
// Set background from another PDF (first page repeated)
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
$result = $pdf->background('/path/back.pdf')
|
||||||
|
->saveAs('/path/watermarked.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set background from another PDF (one page each)
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
$result = $pdf->multiBackground('/path/back_pages.pdf')
|
||||||
|
->saveAs('/path/watermarked.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Add overlay PDF
|
||||||
|
|
||||||
|
Add another PDF file as overlay.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
// Stamp with another PDF (first page repeated)
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
$result = $pdf->stamp('/path/overlay.pdf')
|
||||||
|
->saveAs('/path/stamped.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stamp with another PDF (one page each)
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
$result = $pdf->multiStamp('/path/overlay_pages.pdf')
|
||||||
|
->saveAs('/path/stamped.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Attach Files
|
||||||
|
|
||||||
|
Add file attachments to the document or to a specific page.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
$files = [
|
||||||
|
'/path/to/file1',
|
||||||
|
'/path/to/file2',
|
||||||
|
]
|
||||||
|
|
||||||
|
// Add files at the document level
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
$result = $pdf->attachFiles($files)
|
||||||
|
->saveAs('/path/withfiles.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add files to a specific page
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
$page = 7;
|
||||||
|
$result = $pdf->attachFiles($files, $page)
|
||||||
|
->saveAs('/path/withfiles.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
#### Unpack Files
|
||||||
|
|
||||||
|
Copy file attachments from a PDF to the given directory.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
$result = $pdf->unpackFiles('/path/to/dir');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Generate FDF
|
||||||
|
|
||||||
|
Create a FDF file from a given filled PDF form.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
// Create FDF from PDF
|
||||||
|
$pdf = new Pdf('/path/form.pdf');
|
||||||
|
$result = $pdf->generateFdfFile('/path/data.fdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Get PDF data
|
||||||
|
|
||||||
|
Read out metadata or form field information from a PDF file.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
// Get data
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
$data = $pdf->getData();
|
||||||
|
if ($data === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get form data fields
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
$data = $pdf->getDataFields();
|
||||||
|
if ($data === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get data as string
|
||||||
|
echo $data;
|
||||||
|
$txt = (string) $data;
|
||||||
|
$txt = $data->__toString();
|
||||||
|
|
||||||
|
// Get data as array
|
||||||
|
$arr = (array) $data;
|
||||||
|
$arr = $data->__toArray();
|
||||||
|
$field1 = $data[0]['Field1'];
|
||||||
|
```
|
||||||
|
|
||||||
|
#### How to perform more than one operation on a PDF
|
||||||
|
|
||||||
|
As stated above, you can only perform one of the preceeding operations on a single PDF instance.
|
||||||
|
If you need more than one operation you can feed one `Pdf` instance into another:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
// Extract pages 1-5 and 7,4,9 into a new file
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
$pdf->cat(1, 5)
|
||||||
|
->cat([7, 4, 9]);
|
||||||
|
|
||||||
|
// We now use the above PDF as source file for a new PDF
|
||||||
|
$pdf2 = new Pdf($pdf);
|
||||||
|
$result = $pdf2->fillForm(['name' => 'ÄÜÖ äüö мирано čárka'])
|
||||||
|
->needAppearances()
|
||||||
|
->saveAs('/path/filled.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
You can combine the above operations with one or more of the following options.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
|
||||||
|
$result = $pdf->allow('AllFeatures') // Change permissions
|
||||||
|
->flatten() // Merge form data into document (doesn't work well with UTF-8!)
|
||||||
|
->compress($value) // Compress/Uncompress
|
||||||
|
->keepId('first') // Keep first/last Id of combined files
|
||||||
|
->dropXfa() // Drop newer XFA form from PDF
|
||||||
|
->dropXmp() // Drop newer XMP data from PDF
|
||||||
|
->needAppearances() // Make clients create appearance for form fields
|
||||||
|
->setPassword($pw) // Set owner password
|
||||||
|
->setUserPassword($pw) // Set user password
|
||||||
|
->passwordEncryption(128) // Set password encryption strength
|
||||||
|
->saveAs('new.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example: Fill PDF form and merge form data into PDF
|
||||||
|
// Fill form with data array
|
||||||
|
$result = $pdf = new Pdf('/path/form.pdf');
|
||||||
|
$pdf->fillForm(['name' => 'My Name'])
|
||||||
|
->flatten()
|
||||||
|
->saveAs('/path/filled.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example: Remove password from a PDF
|
||||||
|
$pdf = new Pdf;
|
||||||
|
$result = $pdf->addFile('/path/my.pdf', null, 'some**password')
|
||||||
|
->saveAs('/path/new.pdf');
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Shell Command
|
||||||
|
|
||||||
|
The class uses [php-shellcommand](https://github.com/mikehaertl/php-shellcommand) to execute
|
||||||
|
`pdftk`. You can pass `$options` for its `Command` class as second argument to the constructor:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
$pdf = new Pdf('/path/my.pdf', [
|
||||||
|
'command' => '/some/other/path/to/pdftk',
|
||||||
|
// or on most Windows systems:
|
||||||
|
// 'command' => 'C:\Program Files (x86)\PDFtk\bin\pdftk.exe',
|
||||||
|
'useExec' => true, // May help on Windows systems if execution fails
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Solve issues with UTF-8 characters in filenames or infofile content
|
||||||
|
|
||||||
|
If you have files with UTF-8 encoded characters in their filename or if you
|
||||||
|
pass an infofile with such characters to `updateInfo()` you should supply the
|
||||||
|
correct locale when excuting `pdftk`. You can therefore add these options:
|
||||||
|
|
||||||
|
```php
|
||||||
|
$pdf = new Pdf($file, [
|
||||||
|
'locale' => 'en_US.utf8',
|
||||||
|
'procEnv' => [
|
||||||
|
'LANG' => 'en_US.utf-8',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** You need to ensure that the locale you set here is available on
|
||||||
|
> your system. On Linux you can check with `locale -a` which locales are
|
||||||
|
> installed. [This article](https://wiki.archlinux.org/title/locale) explains
|
||||||
|
> the concept in more detail.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Temporary File
|
||||||
|
|
||||||
|
Internally a temporary file is created via [php-tmpfile](https://github.com/mikehaertl/php-tmpfile).
|
||||||
|
You can also access that file directly, e.g. if you neither want to send or save the
|
||||||
|
file but only need the binary PDF content:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
$result = $pdf->fillForm(['name' => 'My Name'])
|
||||||
|
->execute();
|
||||||
|
if ($result === false) {
|
||||||
|
$error = $pdf->getError();
|
||||||
|
}
|
||||||
|
$content = file_get_contents( (string) $pdf->getTmpFile() );
|
||||||
|
```
|
||||||
|
|
||||||
|
If you have permission issues you may have to set a directory where your
|
||||||
|
`pdftk` command can write to:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use mikehaertl\pdftk\Pdf;
|
||||||
|
|
||||||
|
$pdf = new Pdf('/path/my.pdf');
|
||||||
|
$pdf->tempDir = '/home/john/temp';
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
Please consult the source files for a full documentation of each method.
|
||||||
31
composer/mikehaertl/php-pdftk/composer.json
Normal file
31
composer/mikehaertl/php-pdftk/composer.json
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"name": "mikehaertl/php-pdftk",
|
||||||
|
"description": "A PDF conversion and form utility based on pdftk.",
|
||||||
|
"keywords": ["pdf", "pdftk"],
|
||||||
|
"type": "library",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Michael Haertl",
|
||||||
|
"email": "haertl.mike@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.0",
|
||||||
|
"mikehaertl/php-shellcommand": "^1.6.3",
|
||||||
|
"mikehaertl/php-tmpfile": "^1.1.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": ">4.0 <9.4"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"mikehaertl\\pdftk\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"tests\\": "tests"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
249
composer/mikehaertl/php-pdftk/src/Command.php
Normal file
249
composer/mikehaertl/php-pdftk/src/Command.php
Normal file
|
|
@ -0,0 +1,249 @@
|
||||||
|
<?php
|
||||||
|
namespace mikehaertl\pdftk;
|
||||||
|
|
||||||
|
use mikehaertl\shellcommand\Command as BaseCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command
|
||||||
|
*
|
||||||
|
* This class represents an pdftk shell command. It extends a standard
|
||||||
|
* shellcommand and adds pdftk specific features to add options and operations.
|
||||||
|
*
|
||||||
|
* @author Michael Härtl <haertl.mike@gmail.com>
|
||||||
|
* @license http://www.opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
class Command extends BaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string the pdftk binary
|
||||||
|
*/
|
||||||
|
protected $_command = 'pdftk';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array list of input files to process as array('name' => $filename,
|
||||||
|
* 'password' => $pw) indexed by handle
|
||||||
|
*/
|
||||||
|
protected $_files = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array list of command options, either strings or array with
|
||||||
|
* arguments to addArg()
|
||||||
|
*/
|
||||||
|
protected $_options = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string the operation to perform
|
||||||
|
*/
|
||||||
|
protected $_operation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string|array operation arguments, e.g. a list of page ranges or a
|
||||||
|
* filename or tmp file instance
|
||||||
|
*/
|
||||||
|
protected $_operationArgument = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool whether to force escaping of the operation argument e.g. for
|
||||||
|
* filenames
|
||||||
|
*/
|
||||||
|
protected $_escapeOperationArgument = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name the PDF file to add for processing
|
||||||
|
* @param string $handle one or more uppercase letters A..Z to reference
|
||||||
|
* this file later.
|
||||||
|
* @param string|null $password the owner (or user) password if any
|
||||||
|
* @return Command the command instance for method chaining
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function addFile($name, $handle, $password = null)
|
||||||
|
{
|
||||||
|
$this->checkExecutionStatus();
|
||||||
|
$file = array(
|
||||||
|
'name' => $name,
|
||||||
|
'password' => $password,
|
||||||
|
);
|
||||||
|
$this->_files[$handle] = $file;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $option the pdftk option to add
|
||||||
|
* @param string|File|null $argument the argument to add, either string,
|
||||||
|
* File instance or null if none
|
||||||
|
* @param null|bool whether to escape the option. Default is null meaning
|
||||||
|
* use Command default setting.
|
||||||
|
* @return Command the command instance for method chaining
|
||||||
|
*/
|
||||||
|
public function addOption($option, $argument = null, $escape = null)
|
||||||
|
{
|
||||||
|
$this->_options[] = $argument === null ? $option : array($option, $argument, $escape);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $operation the operation to perform
|
||||||
|
* @return Command the command instance for method chaining
|
||||||
|
*/
|
||||||
|
public function setOperation($operation)
|
||||||
|
{
|
||||||
|
$this->checkExecutionStatus();
|
||||||
|
$this->_operation = $operation;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string|null the current operation or null if none set
|
||||||
|
*/
|
||||||
|
public function getOperation()
|
||||||
|
{
|
||||||
|
return $this->_operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $value the operation argument
|
||||||
|
* @param bool $escape whether to escape the operation argument
|
||||||
|
* @return Command the command instance for method chaining
|
||||||
|
*/
|
||||||
|
public function setOperationArgument($value, $escape = false)
|
||||||
|
{
|
||||||
|
$this->checkExecutionStatus();
|
||||||
|
$this->_operationArgument = $value;
|
||||||
|
$this->_escapeOperationArgument = $escape;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string|array|null the current operation argument as string or
|
||||||
|
* array or null if none set
|
||||||
|
*/
|
||||||
|
public function getOperationArgument()
|
||||||
|
{
|
||||||
|
// Typecast to string in case we have a File instance as argument
|
||||||
|
return is_array($this->_operationArgument) ? $this->_operationArgument : (string) $this->_operationArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int the number of files added to the command
|
||||||
|
*/
|
||||||
|
public function getFileCount()
|
||||||
|
{
|
||||||
|
return count($this->_files);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a page range as used by some operations
|
||||||
|
*
|
||||||
|
* @param int|string|array $start the start page number or an array of page
|
||||||
|
* numbers. If an array, the other arguments will be ignored. $start can
|
||||||
|
* also be bigger than $end for pages in reverse order.
|
||||||
|
* @param int|string|null $end the end page number or null for single page
|
||||||
|
* (or list if $start is an array)
|
||||||
|
* @param string|null $handle the handle of the file to use. Can be null if
|
||||||
|
* only a single file was added.
|
||||||
|
* @param string|null $qualifier the page number qualifier, either 'even'
|
||||||
|
* or 'odd' or null for none
|
||||||
|
* @param string $rotation the rotation to apply to the pages.
|
||||||
|
* @return Command the command instance for method chaining
|
||||||
|
*/
|
||||||
|
public function addPageRange($start, $end = null, $handle = null, $qualifier = null, $rotation = null)
|
||||||
|
{
|
||||||
|
$this->checkExecutionStatus();
|
||||||
|
if (is_array($start)) {
|
||||||
|
if ($handle !== null) {
|
||||||
|
$start = array_map(function ($p) use ($handle) {
|
||||||
|
return $handle . $p;
|
||||||
|
}, $start);
|
||||||
|
}
|
||||||
|
$range = implode(' ', $start);
|
||||||
|
} else {
|
||||||
|
$range = $handle . $start;
|
||||||
|
if ($end) {
|
||||||
|
$range .= '-' . $end;
|
||||||
|
}
|
||||||
|
$range .= $qualifier . $rotation;
|
||||||
|
}
|
||||||
|
$this->_operationArgument[] = $range;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $filename the filename to add as 'output' option or
|
||||||
|
* null if none
|
||||||
|
* @return bool whether the command was executed successfully
|
||||||
|
*/
|
||||||
|
public function execute($filename = null)
|
||||||
|
{
|
||||||
|
$this->checkExecutionStatus();
|
||||||
|
$this->processInputFiles();
|
||||||
|
$this->processOperation();
|
||||||
|
$this->processOptions($filename);
|
||||||
|
return parent::execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process input PDF files and create respective command arguments
|
||||||
|
*/
|
||||||
|
protected function processInputFiles()
|
||||||
|
{
|
||||||
|
$passwords = array();
|
||||||
|
foreach ($this->_files as $handle => $file) {
|
||||||
|
$this->addArg($handle . '=', $file['name']);
|
||||||
|
if ($file['password'] !== null) {
|
||||||
|
$passwords[$handle] = $file['password'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($passwords !== array()) {
|
||||||
|
$this->addArg('input_pw');
|
||||||
|
foreach ($passwords as $handle => $password) {
|
||||||
|
$this->addArg($handle . '=', $password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process options and create respective command arguments
|
||||||
|
* @param string|null $filename if provided an 'output' option will be
|
||||||
|
* added
|
||||||
|
*/
|
||||||
|
protected function processOptions($filename = null)
|
||||||
|
{
|
||||||
|
// output must be first option after operation
|
||||||
|
if ($filename !== null) {
|
||||||
|
$this->addArg('output', $filename, true);
|
||||||
|
}
|
||||||
|
foreach ($this->_options as $option) {
|
||||||
|
if (is_array($option)) {
|
||||||
|
$this->addArg($option[0], $option[1], $option[2]);
|
||||||
|
} else {
|
||||||
|
$this->addArg($option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process opearation and create respective command arguments
|
||||||
|
*/
|
||||||
|
protected function processOperation()
|
||||||
|
{
|
||||||
|
if ($this->_operation !== null) {
|
||||||
|
$value = $this->_operationArgument ? $this->_operationArgument : null;
|
||||||
|
if ($value instanceof TmpFile) {
|
||||||
|
$value = (string) $value;
|
||||||
|
}
|
||||||
|
$this->addArg($this->_operation, $value, $this->_escapeOperationArgument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that the command was not exectued yet. Throws exception
|
||||||
|
* otherwise.
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
protected function checkExecutionStatus()
|
||||||
|
{
|
||||||
|
if ($this->getExecuted()) {
|
||||||
|
throw new \Exception('Operation was already executed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
166
composer/mikehaertl/php-pdftk/src/DataFields.php
Normal file
166
composer/mikehaertl/php-pdftk/src/DataFields.php
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace mikehaertl\pdftk;
|
||||||
|
|
||||||
|
use ArrayObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is an array representation of the dump_data_fields output of
|
||||||
|
* pdftk.
|
||||||
|
*
|
||||||
|
* @author Ray Holland <raymondaholland+php-pdftk@gmail.com>
|
||||||
|
* @author Michael Härtl <haertl.mike@gmail.com>
|
||||||
|
* @license http://www.opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
class DataFields extends ArrayObject
|
||||||
|
{
|
||||||
|
private $_string;
|
||||||
|
private $_array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DataFields constructor.
|
||||||
|
*
|
||||||
|
* @param string $input
|
||||||
|
* @param int $flags
|
||||||
|
* @param string $iterator_class
|
||||||
|
*/
|
||||||
|
public function __construct($input = null, $flags = 0, $iterator_class = "ArrayIterator")
|
||||||
|
{
|
||||||
|
$this->_string = $input ?: '';
|
||||||
|
$this->_array = self::parse($this->_string);
|
||||||
|
|
||||||
|
return parent::__construct($this->_array, $flags, $iterator_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function __toArray()
|
||||||
|
{
|
||||||
|
return $this->_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the output of dump_data_fields into an array.
|
||||||
|
*
|
||||||
|
* The string to parse can either be a single block of `Xyz:value` lines
|
||||||
|
* or a set of such blocks, separated by and starting with `---`.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Here's an example:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* ---
|
||||||
|
* FieldType: Text
|
||||||
|
* FieldName: Text1
|
||||||
|
* FieldFlags: 0
|
||||||
|
* FieldValue: University of Missouri : Ray-Holland
|
||||||
|
* extended line value
|
||||||
|
* FieldValueDefault: University of Missouri : Ray-Holland
|
||||||
|
* extended line2 value
|
||||||
|
* FieldJustification: Left
|
||||||
|
* FieldMaxLength: 99
|
||||||
|
* ---
|
||||||
|
* FieldType: Text
|
||||||
|
* FieldName: Text2
|
||||||
|
* ...
|
||||||
|
* ...
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param $input the string to parse
|
||||||
|
* @return array the parsed result
|
||||||
|
*/
|
||||||
|
public static function parse($input)
|
||||||
|
{
|
||||||
|
if (strncmp('---', $input, 3) === 0) {
|
||||||
|
// Split blocks only if '---' is followed by 'FieldType'
|
||||||
|
$blocks = preg_split(
|
||||||
|
'/^---(\r\n|\n|\r)(?=FieldType:)/m',
|
||||||
|
substr($input, 3)
|
||||||
|
);
|
||||||
|
return array_map('\mikehaertl\pdftk\DataFields::parseBlock', $blocks);
|
||||||
|
} else {
|
||||||
|
return self::parseBlock($input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a block of this form:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* Name1: Value1
|
||||||
|
* Name2: Value2
|
||||||
|
* Name3: Value3
|
||||||
|
* ...
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param string $block the block to parse
|
||||||
|
* @return array the parsed block values indexed by respective names
|
||||||
|
*/
|
||||||
|
public static function parseBlock($block)
|
||||||
|
{
|
||||||
|
$data = array();
|
||||||
|
$lines = preg_split("/(\r\n|\n|\r)/", trim($block));
|
||||||
|
$continueKey = null;
|
||||||
|
foreach ($lines as $n => $line) {
|
||||||
|
if ($continueKey !== null) {
|
||||||
|
$data[$continueKey] .= "\n" . $line;
|
||||||
|
if (!self::lineContinues($lines, $n, $continueKey)) {
|
||||||
|
$continueKey = null;
|
||||||
|
}
|
||||||
|
} elseif (preg_match('/([^:]*): ?(.*)/', $line, $match)) {
|
||||||
|
$key = $match[1];
|
||||||
|
$value = $match[2];
|
||||||
|
// Convert multiple keys like 'FieldStateOption' or 'FieldValue'
|
||||||
|
// from Choice fields to array
|
||||||
|
if (isset($data[$key])) {
|
||||||
|
$data[$key] = (array) $data[$key];
|
||||||
|
$data[$key][] = $value;
|
||||||
|
} else {
|
||||||
|
$data[$key] = $value;
|
||||||
|
}
|
||||||
|
if (self::lineContinues($lines, $n, $key)) {
|
||||||
|
$continueKey = $key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the value for the given line number continues on the next
|
||||||
|
* line, i.e. is a multiline string.
|
||||||
|
*
|
||||||
|
* This can be the case for 'FieldValue' and 'FieldValueDefault' keys. To
|
||||||
|
* find the end of the string we don't simply test for /^Field/, as this
|
||||||
|
* would also match multiline strings where a line starts with 'Field'.
|
||||||
|
*
|
||||||
|
* Instead we assume that the string is always followed by one of these
|
||||||
|
* keys:
|
||||||
|
*
|
||||||
|
* - 'FieldValue:'
|
||||||
|
* - 'FieldValueDefault:'
|
||||||
|
* - 'FieldJustification:'
|
||||||
|
*
|
||||||
|
* @param array $lines all lines of the block
|
||||||
|
* @param int $n the 0-based index of the current line
|
||||||
|
* @param string the key for the value. Only 'FieldValue' and
|
||||||
|
* 'FieldValueDefault' can span multiple lines
|
||||||
|
* @return bool whether the value continues in line n + 1
|
||||||
|
*/
|
||||||
|
protected static function lineContinues($lines, $n, $key)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
in_array($key, array('FieldValue', 'FieldValueDefault')) &&
|
||||||
|
array_key_exists($n + 1, $lines) &&
|
||||||
|
!preg_match('/^Field(Value|ValueDefault|Justification):/', $lines[$n + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
84
composer/mikehaertl/php-pdftk/src/FdfFile.php
Normal file
84
composer/mikehaertl/php-pdftk/src/FdfFile.php
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
namespace mikehaertl\pdftk;
|
||||||
|
|
||||||
|
use mikehaertl\tmp\File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FdfFile
|
||||||
|
*
|
||||||
|
* This class represents a temporary FDF (1.2) file that can be used to fill a
|
||||||
|
* PDF form with valid unicode characters.
|
||||||
|
*
|
||||||
|
* @author Michael Härtl <haertl.mike@gmail.com>
|
||||||
|
* @license http://www.opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
class FdfFile extends File
|
||||||
|
{
|
||||||
|
// FDF file header
|
||||||
|
const FDF_HEADER = <<<FDF
|
||||||
|
%FDF-1.2
|
||||||
|
1 0 obj<</FDF<< /Fields[
|
||||||
|
FDF;
|
||||||
|
|
||||||
|
// FDF file footer
|
||||||
|
const FDF_FOOTER = <<<FDF
|
||||||
|
] >> >>
|
||||||
|
endobj
|
||||||
|
trailer
|
||||||
|
<</Root 1 0 R>>
|
||||||
|
%%EOF
|
||||||
|
FDF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param array $data the form data as name => value
|
||||||
|
* @param string|null $suffix the optional suffix for the tmp file
|
||||||
|
* @param string|null $suffix the optional prefix for the tmp file. If null
|
||||||
|
* 'php_tmpfile_' is used.
|
||||||
|
* @param string|null $directory directory where the file should be
|
||||||
|
* created. Autodetected if not provided.
|
||||||
|
* @param string|null $encoding of the data. Default is 'UTF-8'.
|
||||||
|
*/
|
||||||
|
public function __construct($data, $suffix = null, $prefix = null, $directory = null, $encoding = 'UTF-8')
|
||||||
|
{
|
||||||
|
if ($directory === null) {
|
||||||
|
$directory = self::getTempDir();
|
||||||
|
}
|
||||||
|
$suffix = '.fdf';
|
||||||
|
$prefix = 'php_pdftk_fdf_';
|
||||||
|
|
||||||
|
$this->_fileName = tempnam($directory, $prefix);
|
||||||
|
$newName = $this->_fileName . $suffix;
|
||||||
|
rename($this->_fileName, $newName);
|
||||||
|
$this->_fileName = $newName;
|
||||||
|
|
||||||
|
if (!function_exists('mb_convert_encoding')) {
|
||||||
|
throw new \Exception('MB extension required.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$fields = '';
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
// Create UTF-16BE string encode as ASCII hex
|
||||||
|
// See http://blog.tremily.us/posts/PDF_forms/
|
||||||
|
$utf16Value = mb_convert_encoding($value, 'UTF-16BE', $encoding);
|
||||||
|
|
||||||
|
/* Also create UTF-16BE encoded key, this allows field names containing
|
||||||
|
* german umlauts and most likely many other "special" characters.
|
||||||
|
* See issue #17 (https://github.com/mikehaertl/php-pdftk/issues/17)
|
||||||
|
*/
|
||||||
|
$utf16Key = mb_convert_encoding($key, 'UTF-16BE', $encoding);
|
||||||
|
|
||||||
|
// Escape parenthesis
|
||||||
|
$utf16Value = strtr($utf16Value, array('(' => '\\(', ')' => '\\)'));
|
||||||
|
$fields .= "<</T(" . chr(0xFE) . chr(0xFF) . $utf16Key . ")/V(" . chr(0xFE) . chr(0xFF) . $utf16Value . ")>>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use fwrite, since file_put_contents() messes around with character encoding
|
||||||
|
$fp = fopen($this->_fileName, 'w');
|
||||||
|
fwrite($fp, self::FDF_HEADER);
|
||||||
|
fwrite($fp, $fields);
|
||||||
|
fwrite($fp, self::FDF_FOOTER);
|
||||||
|
fclose($fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
139
composer/mikehaertl/php-pdftk/src/InfoFields.php
Normal file
139
composer/mikehaertl/php-pdftk/src/InfoFields.php
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
<?php
|
||||||
|
namespace mikehaertl\pdftk;
|
||||||
|
|
||||||
|
use ArrayObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class InfoFields
|
||||||
|
* Derived from DataFields
|
||||||
|
*
|
||||||
|
* @author Burak USGURLU <burak@uskur.com.tr>
|
||||||
|
* @license http://www.opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
class InfoFields extends ArrayObject
|
||||||
|
{
|
||||||
|
private $_string;
|
||||||
|
|
||||||
|
private $_array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InfoFields constructor.
|
||||||
|
*
|
||||||
|
* @param string $input
|
||||||
|
* @param int $flags
|
||||||
|
* @param string $iterator_class
|
||||||
|
*/
|
||||||
|
public function __construct($input = null, $flags = 0, $iterator_class = "ArrayIterator")
|
||||||
|
{
|
||||||
|
$this->_string = $input ?: '';
|
||||||
|
$this->_array = $this->parseData($this->_string);
|
||||||
|
|
||||||
|
return parent::__construct($this->_array, $flags, $iterator_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function __toArray()
|
||||||
|
{
|
||||||
|
return $this->_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the output of dump_data into something usable.
|
||||||
|
*
|
||||||
|
* The expected string looks similar to this:
|
||||||
|
*
|
||||||
|
* InfoBegin
|
||||||
|
* InfoKey: Creator
|
||||||
|
* InfoValue: Adobe Acrobat Pro DC 15.0
|
||||||
|
* InfoBegin
|
||||||
|
* InfoKey: Producer
|
||||||
|
* InfoValue: XYZ
|
||||||
|
* PdfID0: 1fdce9ed1153ab4c973334b512a67997
|
||||||
|
* PdfID1: c7acc878cda02ad7bb401fa8080a8929
|
||||||
|
* NumberOfPages: 11
|
||||||
|
* BookmarkBegin
|
||||||
|
* BookmarkTitle: First bookmark
|
||||||
|
* BookmarkLevel: 1
|
||||||
|
* BookmarkPageNumber: 1
|
||||||
|
* BookmarkBegin
|
||||||
|
* BookmarkTitle: Second bookmark
|
||||||
|
* BookmarkLevel: 1
|
||||||
|
* BookmarkPageNumber: 2
|
||||||
|
*
|
||||||
|
* @param $dataString
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function parseData($dataString)
|
||||||
|
{
|
||||||
|
$output = array();
|
||||||
|
foreach (explode(PHP_EOL, $dataString) as $line) {
|
||||||
|
$trimmedLine = trim($line);
|
||||||
|
// Parse blocks of the form:
|
||||||
|
// AbcBegin
|
||||||
|
// AbcData1: Value1
|
||||||
|
// AbcData2: Value2
|
||||||
|
// AbcBegin
|
||||||
|
// AbcData1: Value3
|
||||||
|
// AbcData2: Value4
|
||||||
|
// ...
|
||||||
|
if (preg_match('/^(\w+)Begin$/', $trimmedLine, $matches)) {
|
||||||
|
// Previous group ended - if any - so add it to output
|
||||||
|
if (!empty($group) && !empty($groupData)) {
|
||||||
|
$output[$group][] = $groupData;
|
||||||
|
}
|
||||||
|
// Now start next group
|
||||||
|
$group = $matches[1]; // Info, PageMedia, ...
|
||||||
|
if (!isset($output[$group])) {
|
||||||
|
$output[$group] = array();
|
||||||
|
}
|
||||||
|
$groupData = array();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!empty($group)) {
|
||||||
|
// Check for AbcData1: Value1
|
||||||
|
if (preg_match("/^$group(\w+): ?(.*)$/", $trimmedLine, $matches)) {
|
||||||
|
$groupData[$matches[1]] = $matches[2];
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// Something else, so group ended
|
||||||
|
if (!empty($groupData)) {
|
||||||
|
$output[$group][] = $groupData;
|
||||||
|
$groupData = array();
|
||||||
|
}
|
||||||
|
$group = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (preg_match('/([^:]*): ?(.*)/', $trimmedLine, $matches)) {
|
||||||
|
$output[$matches[1]] = $matches[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// There could be a final group left if it was not followed by another
|
||||||
|
// line in the loop
|
||||||
|
if (!empty($group) && !empty($groupData)) {
|
||||||
|
$output[$group][] = $groupData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info group is a list of ['Key' => 'x', 'Value' => 'y'], so
|
||||||
|
// convert it to ['x' => 'y', ...]
|
||||||
|
if (isset($output['Info'])) {
|
||||||
|
$data = array();
|
||||||
|
foreach ($output['Info'] as $infoGroup) {
|
||||||
|
if (isset($infoGroup['Key'], $infoGroup['Value'])) {
|
||||||
|
$data[$infoGroup['Key']] = $infoGroup['Value'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$output['Info'] = $data;
|
||||||
|
}
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
}
|
||||||
190
composer/mikehaertl/php-pdftk/src/InfoFile.php
Normal file
190
composer/mikehaertl/php-pdftk/src/InfoFile.php
Normal file
|
|
@ -0,0 +1,190 @@
|
||||||
|
<?php
|
||||||
|
namespace mikehaertl\pdftk;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use mikehaertl\tmp\File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InfoFile
|
||||||
|
*
|
||||||
|
* This class represents a temporary dump_data compatible file that can be used to update meta data of PDF
|
||||||
|
* with valid unicode characters.
|
||||||
|
*
|
||||||
|
* @author Burak Usgurlu <burak@uskur.com.tr>
|
||||||
|
* @license http://www.opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
class InfoFile extends File
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string[] list of valid keys for the document information directory of
|
||||||
|
* the PDF. These will be converted into `InfoBegin... InfoKey... InvoValue`
|
||||||
|
* blocks on the output.
|
||||||
|
*
|
||||||
|
* See section 14.3.3 in https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf
|
||||||
|
*/
|
||||||
|
public static $documentInfoFields = array(
|
||||||
|
'Title',
|
||||||
|
'Author',
|
||||||
|
'Subject',
|
||||||
|
'Keywords',
|
||||||
|
'Creator',
|
||||||
|
'Producer',
|
||||||
|
'CreationDate',
|
||||||
|
'ModDate',
|
||||||
|
'Trapped',
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param array|InfoFields $data the data in this format:
|
||||||
|
* ```
|
||||||
|
* [
|
||||||
|
* 'Info' => [
|
||||||
|
* 'Title' => '...',
|
||||||
|
* 'Author' => '...',
|
||||||
|
* 'Subject' => '...',
|
||||||
|
* 'Keywords' => '...',
|
||||||
|
* 'Creator' => '...',
|
||||||
|
* 'Producer' => '...',
|
||||||
|
* 'CreationDate' => '...',
|
||||||
|
* 'ModDate' => '...',
|
||||||
|
* 'Trapped' => '...',
|
||||||
|
* ],
|
||||||
|
* 'Bookmark' => [
|
||||||
|
* [
|
||||||
|
* 'Title' => '...',
|
||||||
|
* 'Level' => ...,
|
||||||
|
* 'PageNumber' => ...,
|
||||||
|
* ],
|
||||||
|
* ],
|
||||||
|
* 'PageMedia' => [ ... ],
|
||||||
|
* 'PageLabel' => [ ... ],
|
||||||
|
* // ...
|
||||||
|
* ]
|
||||||
|
* ```
|
||||||
|
* This is the same format as the InfoFields object that is returned
|
||||||
|
* by `getData()` if you cast it to an array. You can also pass such an
|
||||||
|
* (optionally modified) object as input. Some fields like 'NumberOfPages'
|
||||||
|
* or 'PdfID0' are ignored as those are not part of the PDF's metadata.
|
||||||
|
* All array elements are optional.
|
||||||
|
* @param string|null $suffix the optional suffix for the tmp file
|
||||||
|
* @param string|null $suffix the optional prefix for the tmp file. If null
|
||||||
|
* 'php_tmpfile_' is used.
|
||||||
|
* @param string|null $directory directory where the file should be
|
||||||
|
* created. Autodetected if not provided.
|
||||||
|
* @param string|null $encoding of the data. Default is 'UTF-8'. If the
|
||||||
|
* data has another encoding it will be converted to UTF-8. This requires
|
||||||
|
* the mbstring extension to be installed.
|
||||||
|
* @throws Exception on invalid data format or if mbstring extension is
|
||||||
|
* missing and data must be converted
|
||||||
|
*/
|
||||||
|
public function __construct($data, $suffix = null, $prefix = null, $directory = null, $encoding = 'UTF-8')
|
||||||
|
{
|
||||||
|
if ($suffix === null) {
|
||||||
|
$suffix = '.txt';
|
||||||
|
}
|
||||||
|
if ($prefix === null) {
|
||||||
|
$prefix = 'php_pdftk_info_';
|
||||||
|
}
|
||||||
|
if ($directory === null) {
|
||||||
|
$directory = self::getTempDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
$tempName = tempnam($directory, $prefix);
|
||||||
|
$newName = $tempName . $suffix;
|
||||||
|
rename($tempName, $newName);
|
||||||
|
$this->_fileName = $newName;
|
||||||
|
|
||||||
|
if ($encoding !== 'UTF-8' && !function_exists('mb_convert_encoding')) {
|
||||||
|
throw new Exception('mbstring extension required.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$fields = '';
|
||||||
|
$normalizedData = self::normalize($data);
|
||||||
|
|
||||||
|
foreach ($normalizedData as $block => $items) {
|
||||||
|
$fields .= self::renderBlock($block, $items, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use fwrite, since file_put_contents() messes around with character encoding
|
||||||
|
$fp = fopen($this->_fileName, 'w');
|
||||||
|
fwrite($fp, $fields);
|
||||||
|
fclose($fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize the input data
|
||||||
|
*
|
||||||
|
* This also converts data from the legacy format (<0.13.0) to the new
|
||||||
|
* input format described in the constructor.
|
||||||
|
*
|
||||||
|
* @param array $data the data to normalize
|
||||||
|
* @return array a normalized array in the format described in the constructor
|
||||||
|
*/
|
||||||
|
private static function normalize($data)
|
||||||
|
{
|
||||||
|
$normalized = array();
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
if (in_array($key, self::$documentInfoFields)) {
|
||||||
|
$normalized['Info'][$key] = $value;
|
||||||
|
} elseif (is_array($value)) {
|
||||||
|
if (!isset($normalized[$key])) {
|
||||||
|
$normalized[$key] = array();
|
||||||
|
}
|
||||||
|
$normalized[$key] = array_merge($normalized[$key], $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a set of block fields
|
||||||
|
*
|
||||||
|
* @param string $block like 'Info', 'Bookmark', etc.
|
||||||
|
* @param array $items the field items to render
|
||||||
|
* @param string $encoding the encoding of the item data
|
||||||
|
* @return string the rendered fields
|
||||||
|
*/
|
||||||
|
private static function renderBlock($block, $items, $encoding)
|
||||||
|
{
|
||||||
|
$fields = '';
|
||||||
|
foreach ($items as $key => $value) {
|
||||||
|
if ($block === 'Info') {
|
||||||
|
$fields .= self::renderField($block, $key, $value, $encoding, true);
|
||||||
|
} else {
|
||||||
|
$fields .= "{$block}Begin\n";
|
||||||
|
foreach ($value as $subKey => $subValue) {
|
||||||
|
$fields .= self::renderField($block, $subKey, $subValue, $encoding, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a field in a given input block
|
||||||
|
*
|
||||||
|
* @param string $prefix the prefix to use for the field
|
||||||
|
* @param string $key the field key
|
||||||
|
* @param string $value the field value
|
||||||
|
* @param string $encoding the endoding of key and value
|
||||||
|
* @param bool $isInfo whether it's an 'Info' field
|
||||||
|
* @return string the rendered field
|
||||||
|
*/
|
||||||
|
private static function renderField($prefix, $key, $value, $encoding, $isInfo)
|
||||||
|
{
|
||||||
|
if ($encoding !== 'UTF-8') {
|
||||||
|
$value = mb_convert_encoding($value, 'UTF-8', $encoding);
|
||||||
|
$key = mb_convert_encoding($key, 'UTF-8', $encoding);
|
||||||
|
$value = defined('ENT_XML1') ? htmlspecialchars($key, ENT_XML1, 'UTF-8') : htmlspecialchars($key);
|
||||||
|
$key = defined('ENT_XML1') ? htmlspecialchars($value, ENT_XML1, 'UTF-8') : htmlspecialchars($value);
|
||||||
|
}
|
||||||
|
if ($isInfo) {
|
||||||
|
return "InfoBegin\nInfoKey: $key\nInfoValue: $value\n";
|
||||||
|
} else {
|
||||||
|
return "{$prefix}{$key}: $value\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
749
composer/mikehaertl/php-pdftk/src/Pdf.php
Normal file
749
composer/mikehaertl/php-pdftk/src/Pdf.php
Normal file
|
|
@ -0,0 +1,749 @@
|
||||||
|
<?php
|
||||||
|
namespace mikehaertl\pdftk;
|
||||||
|
|
||||||
|
use mikehaertl\tmp\File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pdf
|
||||||
|
*
|
||||||
|
* This class is a wrapper around pdftk.
|
||||||
|
*
|
||||||
|
* The class was developed for pdftk 2.x but should also work with older
|
||||||
|
* versions, but you may have to use slightly different page rotation options
|
||||||
|
* (e.g 'E' instead 'east').
|
||||||
|
*
|
||||||
|
* @author Michael Härtl <haertl.mike@gmail.com>
|
||||||
|
* @license http://www.opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
class Pdf
|
||||||
|
{
|
||||||
|
// The prefix for temporary files
|
||||||
|
const TMP_PREFIX = 'tmp_php_pdftk_';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool whether to ignore any errors if some non-empty output file was
|
||||||
|
* still created. Default is false.
|
||||||
|
*/
|
||||||
|
public $ignoreWarnings = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var null|string an optional directory where temporary files should be
|
||||||
|
* created. If left empty the directory is autodetected.
|
||||||
|
*/
|
||||||
|
public $tempDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var File the temporary output file
|
||||||
|
*/
|
||||||
|
protected $_tmpFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string the content type of the tmp output
|
||||||
|
*/
|
||||||
|
protected $_tmpOutputContentType = 'application/pdf';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Command the command instance that executes pdftk
|
||||||
|
*/
|
||||||
|
protected $_command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int a counter for autogenerated handles
|
||||||
|
*/
|
||||||
|
protected $_handle = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string the error message
|
||||||
|
*/
|
||||||
|
protected $_error = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string|null the output filename. If null (default) a tmp file is
|
||||||
|
* used as output. If false, no output option is added at all.
|
||||||
|
*/
|
||||||
|
protected $_output;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string the PDF data as returned from getData()
|
||||||
|
*/
|
||||||
|
protected $_data;
|
||||||
|
protected $_data_utf8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var DataFields the PDF form field data as returned from getDataFields()
|
||||||
|
*/
|
||||||
|
protected $_dataFields;
|
||||||
|
protected $_dataFields_utf8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Pdf[]|null if the input was an instance, we keep a reference here,
|
||||||
|
* so that it won't get unlinked before this object gets destroyed
|
||||||
|
*/
|
||||||
|
protected $_pdfs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|Pdf|array $pdf a pdf filename or Pdf instance or an array
|
||||||
|
* of filenames/instances indexed by a handle. The array values can also
|
||||||
|
* be arrays of the form array($filename, $password) if some files are
|
||||||
|
* password protected.
|
||||||
|
* @param array $options Options to pass to set on the Command instance,
|
||||||
|
* e.g. the pdftk binary path
|
||||||
|
*/
|
||||||
|
public function __construct($pdf = null, $options = array())
|
||||||
|
{
|
||||||
|
$command = $this->getCommand();
|
||||||
|
if ($options !== array()) {
|
||||||
|
$command->setOptions($options);
|
||||||
|
}
|
||||||
|
if (is_string($pdf) || $pdf instanceof Pdf) {
|
||||||
|
$this->addFile($pdf);
|
||||||
|
} elseif (is_array($pdf)) {
|
||||||
|
foreach ($pdf as $handle => $file) {
|
||||||
|
if (is_array($file)) {
|
||||||
|
$this->addFile($file[0], $handle, $file[1]);
|
||||||
|
} else {
|
||||||
|
$this->addFile($file, $handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|Pdf $name the PDF filename or Pdf instance to add for
|
||||||
|
* processing
|
||||||
|
* @param string|null $handle one or more uppercase letters A..Z to
|
||||||
|
* reference this file later. If no handle is provided, an internal handle
|
||||||
|
* is autocreated, consuming the range Z..A
|
||||||
|
* @param string|null $password the owner (or user) password if any
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function addFile($name, $handle = null, $password = null)
|
||||||
|
{
|
||||||
|
if ($handle === null || is_numeric($handle)) {
|
||||||
|
$handle = $this->nextHandle();
|
||||||
|
}
|
||||||
|
if ($name instanceof Pdf) {
|
||||||
|
// Keep a reference to the object to prevent unlinking
|
||||||
|
$this->_pdfs[] = $name;
|
||||||
|
if (!$name->getCommand()->getExecuted()) {
|
||||||
|
// @todo: Catch errors!
|
||||||
|
$name->execute();
|
||||||
|
}
|
||||||
|
$name = (string) $name->getTmpFile();
|
||||||
|
}
|
||||||
|
$this->getCommand()->addFile($name, $handle, $password);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assemble (catenate) pages from the input files.
|
||||||
|
*
|
||||||
|
* Values for rotation are (in degrees): north: 0, east: 90, south: 180,
|
||||||
|
* west: 270, left: -90, right: +90, down: +180. left, right and down make
|
||||||
|
* relative adjustments to a page's rotation. Note: Older pdftk versions
|
||||||
|
* use N, E, S, W, L, R, and D instead.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* $pdf = new Pdf;
|
||||||
|
* $pdf->addFile('file1.pdf', 'A')
|
||||||
|
* ->addFile('file2.pdf', 'B')
|
||||||
|
* ->cat(array(1,3),'B')) // pages 1 and 3 of file B
|
||||||
|
* ->cat(1, 5, 'A', 'odd') // pages 1, 3, 5 of file A
|
||||||
|
* ->cat('end', 5, 'B') // pages 5 to end of file B in reverse order
|
||||||
|
* ->cat(null, null, 'B', 'east') // All pages from file B rotated by 90 degree
|
||||||
|
* ->saveAs('out.pdf');
|
||||||
|
* or
|
||||||
|
* $files = ['file1.pdf', 'file2.pdf', 'file3.pdf'];
|
||||||
|
* $pdf = new Pdf($files);
|
||||||
|
* $pdf->cat() // all files, all pages
|
||||||
|
* ->saveAs('out.pdf');
|
||||||
|
*
|
||||||
|
* @param int|string|array|null $start the start page number or an array of page
|
||||||
|
* numbers. If an array, the other arguments will be ignored. $start can
|
||||||
|
* also be bigger than $end for pages in reverse order. If $start is null all
|
||||||
|
* pages of all files will be added.
|
||||||
|
* @param int|string|null $end the end page number or null for single page
|
||||||
|
* (or list if $start is an array)
|
||||||
|
* @param string|null $handle the handle of the file to use. Can be null if
|
||||||
|
* only a single file was added.
|
||||||
|
* @param string|null $qualifier the page number qualifier, either 'even'
|
||||||
|
* or 'odd' or null for none
|
||||||
|
* @param string $rotation the rotation to apply to the pages.
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function cat($start = null, $end = null, $handle = null, $qualifier = null, $rotation = null)
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->setOperation('cat')
|
||||||
|
->addPageRange($start, $end, $handle, $qualifier, $rotation);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuffle pages from the input files.
|
||||||
|
*
|
||||||
|
* This works the same as cat(), but each call to this method creates a
|
||||||
|
* "stream" of pages. The outfile will be assembled by adding one page from
|
||||||
|
* each stream at a time.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* $pdf = new Pdf;
|
||||||
|
* $pdf1 = $pdf->addFile('file1.pdf');
|
||||||
|
* $pdf->shuffle($pdf1, array(1,3,2))
|
||||||
|
* ->shuffle($pdf1, array(4,5,9)
|
||||||
|
* ->saveAs('out.pdf');
|
||||||
|
*
|
||||||
|
* This will give the page order 1, 4, 3, 5, 2, 9 in the out.pdf
|
||||||
|
*
|
||||||
|
* @param string $handle the handle of the input file to use
|
||||||
|
* @param int|array $start the start page number or an array of page
|
||||||
|
* numbers.
|
||||||
|
* @param int|null $end the end page number or null for single page (or
|
||||||
|
* list if $start is an array)
|
||||||
|
* @param string|null $qualifier the page number qualifier, either 'even'
|
||||||
|
* or 'odd' or null for none
|
||||||
|
* @param string $rotation the rotation to apply to the pages. See cat()
|
||||||
|
* for more details.
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function shuffle($start, $end = null, $handle = null, $qualifier = null, $rotation = null)
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->setOperation('shuffle')
|
||||||
|
->addPageRange($start, $end, $handle, $qualifier, $rotation);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split the PDF document into pages
|
||||||
|
*
|
||||||
|
* @param string|null $filepattern the output name in sprintf format or
|
||||||
|
* null for default 'pg_%04d.pdf'
|
||||||
|
* @return bool whether the burst operation was successful
|
||||||
|
*/
|
||||||
|
public function burst($filepattern = null)
|
||||||
|
{
|
||||||
|
$this->constrainSingleFile();
|
||||||
|
$this->getCommand()->setOperation('burst');
|
||||||
|
$this->_output = $filepattern === null ? 'pg_%04d.pdf' : $filepattern;
|
||||||
|
return $this->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach files to the PDF
|
||||||
|
*
|
||||||
|
* @param array $files the list of full paths to the files to attach
|
||||||
|
* @param string $toPage the page to add the attachment to. If omitted the
|
||||||
|
* files are attached at the document level.
|
||||||
|
* @return bool whether the operation was successful
|
||||||
|
*/
|
||||||
|
public function attachFiles($files, $toPage = null)
|
||||||
|
{
|
||||||
|
$this->constrainSingleFile();
|
||||||
|
if ($toPage !== null) {
|
||||||
|
$files[] = 'to_page';
|
||||||
|
$files[] = $toPage;
|
||||||
|
}
|
||||||
|
$this->getCommand()
|
||||||
|
->setOperation('attach_files')
|
||||||
|
->setOperationArgument($files, true);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy all attachments from the PDF to the given directory
|
||||||
|
*
|
||||||
|
* @param string|null $dir the output directory
|
||||||
|
* @return bool whether the operation was successful
|
||||||
|
*/
|
||||||
|
public function unpackFiles($dir = null)
|
||||||
|
{
|
||||||
|
$this->constrainSingleFile();
|
||||||
|
$this->getCommand()->setOperation('unpack_files');
|
||||||
|
$this->_output = $dir;
|
||||||
|
return $this->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the FDF file for a single PDF file.
|
||||||
|
*
|
||||||
|
* @param string $name name of the FDF file
|
||||||
|
* @return bool whether the pdf is generated successful
|
||||||
|
*/
|
||||||
|
public function generateFdfFile($name)
|
||||||
|
{
|
||||||
|
$this->constrainSingleFile();
|
||||||
|
$this->getCommand()->setOperation('generate_fdf');
|
||||||
|
$this->_output = $name;
|
||||||
|
return $this->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill a PDF form
|
||||||
|
*
|
||||||
|
* @param string|array $data either a XFDF/FDF filename or an array with
|
||||||
|
* form field data (name => value)
|
||||||
|
* @param string $encoding the encoding of the data. Default is 'UTF-8'.
|
||||||
|
* @param bool $dropXfa whether to drop XFA forms (see dropXfa()). Default
|
||||||
|
* is true.
|
||||||
|
* @param string $format the file format to use for form filling when
|
||||||
|
* passing an array in `$data`. This can be `xfdf` or `fdf`. `xfdf` should
|
||||||
|
* give best results so you should not have to change the default.
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function fillForm($data, $encoding = 'UTF-8', $dropXfa = true, $format = 'xfdf')
|
||||||
|
{
|
||||||
|
$this->constrainSingleFile();
|
||||||
|
if (is_array($data)) {
|
||||||
|
$className = '\mikehaertl\pdftk\\' . ($format === 'xfdf' ? 'XfdfFile' : 'FdfFile');
|
||||||
|
$data = new $className($data, null, null, $this->tempDir, $encoding);
|
||||||
|
}
|
||||||
|
$this->getCommand()
|
||||||
|
->setOperation('fill_form')
|
||||||
|
->setOperationArgument($data, true);
|
||||||
|
|
||||||
|
if ($dropXfa) {
|
||||||
|
$this->dropXfa();
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update meta data of PDF
|
||||||
|
*
|
||||||
|
* @param string|array $data either a InfoFile filename or an array with
|
||||||
|
* form field data (name => value)
|
||||||
|
* @param string the encoding of the data. Default is 'UTF-8'.
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function updateInfo($data, $encoding = 'UTF-8')
|
||||||
|
{
|
||||||
|
$this->constrainSingleFile();
|
||||||
|
if (is_array($data) || $data instanceof InfoFields) {
|
||||||
|
$data = new InfoFile($data, null, null, $this->tempDir, $encoding);
|
||||||
|
}
|
||||||
|
$this->getCommand()
|
||||||
|
->setOperation($encoding == 'UTF-8' ? 'update_info_utf8' : 'update_info')
|
||||||
|
->setOperationArgument($data, true);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply a PDF as watermark to the background of a single PDF file.
|
||||||
|
*
|
||||||
|
* The PDF file must have a transparent background for the watermark to be
|
||||||
|
* visible.
|
||||||
|
*
|
||||||
|
* @param string $file name of the background PDF file. Only the first page
|
||||||
|
* is used.
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function background($file)
|
||||||
|
{
|
||||||
|
$this->constrainSingleFile();
|
||||||
|
$this->getCommand()
|
||||||
|
->setOperation('background')
|
||||||
|
->setOperationArgument($file, true);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply multiple PDF pages as watermark to the corresponding pages of a
|
||||||
|
* single PDF file.
|
||||||
|
*
|
||||||
|
* If $file has fewer pages than the PDF file then the last page is
|
||||||
|
* repeated as background.
|
||||||
|
*
|
||||||
|
* @param string $file name of the background PDF file.
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function multiBackground($file)
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->setOperation('multibackground')
|
||||||
|
->setOperationArgument($file, true);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add $file as overlay to a single PDF file.
|
||||||
|
*
|
||||||
|
* The $file should have a transparent background.
|
||||||
|
*
|
||||||
|
* @param string $file name of the PDF file to add as overlay. Only the
|
||||||
|
* first page is used.
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function stamp($file)
|
||||||
|
{
|
||||||
|
$this->constrainSingleFile();
|
||||||
|
$this->getCommand()
|
||||||
|
->setOperation('stamp')
|
||||||
|
->setOperationArgument($file, true);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add multiple pages from $file as overlay to the corresponding pages of a
|
||||||
|
* single PDF file.
|
||||||
|
*
|
||||||
|
* If $file has fewer pages than the PDF file then the last page is
|
||||||
|
* repeated as overlay.
|
||||||
|
*
|
||||||
|
* @param string $file name of the PDF file to add as overlay
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function multiStamp($file)
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->setOperation('multistamp')
|
||||||
|
->setOperationArgument($file, true);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $utf8 whether to dump the data UTF-8 encoded. Default is
|
||||||
|
* true.
|
||||||
|
* @return InfoFields|bool meta data about the PDF or false on failure
|
||||||
|
*/
|
||||||
|
public function getData($utf8 = true)
|
||||||
|
{
|
||||||
|
$property = $utf8 ? '_data_utf8' : '_data';
|
||||||
|
if ($this->$property === null) {
|
||||||
|
$command = $this->getCommand();
|
||||||
|
$command->setOperation($utf8 ? 'dump_data_utf8' : 'dump_data');
|
||||||
|
if (!$command->execute()) {
|
||||||
|
$this->_error = $command->getError();
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
$this->$property = new InfoFields(trim($command->getOutput()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this->$property;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $utf8 whether to dump the data UTF-8 encoded. Default is
|
||||||
|
* true.
|
||||||
|
* @return DataFields|bool data about the PDF form fields or false on
|
||||||
|
* failure
|
||||||
|
*/
|
||||||
|
public function getDataFields($utf8 = true)
|
||||||
|
{
|
||||||
|
$property = $utf8 ? '_dataFields_utf8' : '_dataFields';
|
||||||
|
if ($this->$property === null) {
|
||||||
|
$command = $this->getCommand();
|
||||||
|
$command->setOperation($utf8 ? 'dump_data_fields_utf8' : 'dump_data_fields');
|
||||||
|
if (!$command->execute()) {
|
||||||
|
$this->_error = $command->getError();
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
$this->$property = new DataFields(trim($command->getOutput()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this->$property;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set PDF permissions
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param string|null $permissions list of space separated permissions or
|
||||||
|
* null for none. The available permissions are Printing, DegradedPrinting,
|
||||||
|
* ModifyContents, Assembly, CopyContents, ScreenReaders,
|
||||||
|
* ModifyAnnotations, FillIn, AllFeatures.
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function allow($permissions = null)
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->addOption('allow', $permissions, false);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flatten the PDF form fields values into a single PDF file.
|
||||||
|
*
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function flatten()
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->addOption('flatten');
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore/remove compression
|
||||||
|
*
|
||||||
|
* @param bool $compress whether to restore (default) or remove the
|
||||||
|
* compression
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function compress($compress = true)
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->addOption($compress ? 'compress' : 'uncompress');
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When combining multiple PDFs, use either the first or last ID in the
|
||||||
|
* output. If not called, a new ID is created.
|
||||||
|
*
|
||||||
|
* @param string $id, either 'first' (default) or 'last'
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function keepId($id = 'first')
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->addOption($id === 'first' ? 'keep_first_id' : 'keep_final_id');
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set need_appearances flag in PDF
|
||||||
|
*
|
||||||
|
* This flag makes sure, that a PDF reader takes care of rendering form
|
||||||
|
* field content, even if it contains non ASCII characters. You should
|
||||||
|
* always use this option if you fill in forms e.g. with Unicode
|
||||||
|
* characters. You can't combine this option with flatten() though!
|
||||||
|
*
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function needAppearances()
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->addOption('need_appearances');
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop XFA data from forms created with newer Acrobat.
|
||||||
|
*
|
||||||
|
* Newer PDF forms contain both, the newer XFA and the older AcroForm form
|
||||||
|
* fields. PDF readers can use both, but will prefer XFA if present. Since
|
||||||
|
* pdftk can only fill in AcroForm data you should always add this option
|
||||||
|
* when filling in forms with pdftk.
|
||||||
|
*
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function dropXfa()
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->addOption('drop_xfa');
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop XMP meta data
|
||||||
|
*
|
||||||
|
* Newer PDFs can contain both, new style XMP data and old style info
|
||||||
|
* directory. PDF readers can use both, but will prefer XMP if present.
|
||||||
|
* Since pdftk can only update the info directory you should always add
|
||||||
|
* this option when updating PDF info.
|
||||||
|
*
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function dropXmp()
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->addOption('drop_xmp');
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $password the owner password to set on the output PDF
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function setPassword($password)
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->addOption('owner_pw', $password, true);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $password the user password to set on the output PDF
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function setUserPassword($password)
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->addOption('user_pw', $password, true);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $strength the password encryption strength. Default is 128
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function passwordEncryption($strength = 128)
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->addOption($strength == 128 ? 'encrypt_128bit' : 'encrypt_40bit');
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace embedded font with a local font when filling a form.
|
||||||
|
*
|
||||||
|
* This option is only available for pdftk-java >= 3.3.0. It is useful when
|
||||||
|
* filling a form with non-ASCII text that is not supported by the fonts
|
||||||
|
* included in the input PDF.
|
||||||
|
*
|
||||||
|
* @param string $fontName the path to the font or the name of a font family.
|
||||||
|
* @return Pdf the pdf instance for method chaining
|
||||||
|
*/
|
||||||
|
public function replacementFont($path)
|
||||||
|
{
|
||||||
|
$this->getCommand()
|
||||||
|
->addOption('replacement_font', $path);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the operation and save the output file
|
||||||
|
*
|
||||||
|
* @param string $name of output file
|
||||||
|
* @return bool whether the PDF could be processed and saved
|
||||||
|
*/
|
||||||
|
public function saveAs($name)
|
||||||
|
{
|
||||||
|
if (!$this->getCommand()->getExecuted() && !$this->execute()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$tmpFile = (string) $this->getTmpFile();
|
||||||
|
if (!copy($tmpFile, $name)) {
|
||||||
|
$this->_error = "Could not copy PDF from tmp location '$tmpFile' to '$name'";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send PDF to client, either inline or as download (triggers PDF creation)
|
||||||
|
*
|
||||||
|
* @param string|null $filename the filename to send. If empty, the PDF is
|
||||||
|
* streamed inline.
|
||||||
|
* @param bool $inline whether to force inline display of the PDF, even if
|
||||||
|
* filename is present.
|
||||||
|
* @param array $headers a list of additional HTTP headers to send in the
|
||||||
|
* response as an array. The array keys are the header names like
|
||||||
|
* 'Cache-Control' and the array values the header value strings to send.
|
||||||
|
* Each array value can also be another array of strings if the same header
|
||||||
|
* should be sent multiple times. This can also be used to override
|
||||||
|
* automatically created headers like 'Expires' or 'Content-Length'. To suppress
|
||||||
|
* automatically created headers, `false` can also be used as header value.
|
||||||
|
* @return bool whether PDF was created successfully
|
||||||
|
*/
|
||||||
|
public function send($filename = null, $inline = false, $headers = array())
|
||||||
|
{
|
||||||
|
if (!$this->getCommand()->getExecuted() && !$this->execute()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$this->getTmpFile()->send($filename, $this->_tmpOutputContentType, $inline, $headers);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the raw PDF contents (triggers PDF creation).
|
||||||
|
*
|
||||||
|
* @return string|bool the PDF content as a string or `false` if the PDF
|
||||||
|
* wasn't created successfully.
|
||||||
|
*/
|
||||||
|
public function toString()
|
||||||
|
{
|
||||||
|
if (!$this->getCommand()->getExecuted() && !$this->execute()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return file_get_contents($this->getTmpFile()->getFileName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Command the command instance that executes pdftk
|
||||||
|
*/
|
||||||
|
public function getCommand()
|
||||||
|
{
|
||||||
|
if ($this->_command === null) {
|
||||||
|
$this->_command = new Command;
|
||||||
|
}
|
||||||
|
return $this->_command;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return File the temporary output file instance
|
||||||
|
*/
|
||||||
|
public function getTmpFile()
|
||||||
|
{
|
||||||
|
if ($this->_tmpFile === null) {
|
||||||
|
$this->_tmpFile = new File('', '.pdf', self::TMP_PREFIX, $this->tempDir);
|
||||||
|
}
|
||||||
|
return $this->_tmpFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string the error message or an empty string if none
|
||||||
|
*/
|
||||||
|
public function getError()
|
||||||
|
{
|
||||||
|
return $this->_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the pdftk command and store the output file to a temporary
|
||||||
|
* location or $this->_output if set. You should probably never call this
|
||||||
|
* method unless you only need a temporary PDF file as result.
|
||||||
|
*
|
||||||
|
* @return bool whether the command was executed successfully
|
||||||
|
*/
|
||||||
|
public function execute()
|
||||||
|
{
|
||||||
|
$command = $this->getCommand();
|
||||||
|
if ($command->getExecuted()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->_output === false) {
|
||||||
|
$filename = null;
|
||||||
|
} else {
|
||||||
|
$filename = $this->_output ? $this->_output : (string) $this->getTmpFile();
|
||||||
|
}
|
||||||
|
if (!$command->execute($filename)) {
|
||||||
|
$this->_error = $command->getError();
|
||||||
|
if ($filename && !(file_exists($filename) && filesize($filename) !== 0 && $this->ignoreWarnings)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure, that only one file is present
|
||||||
|
*/
|
||||||
|
protected function constrainSingleFile()
|
||||||
|
{
|
||||||
|
if ($this->getCommand()->getFileCount() > 1) {
|
||||||
|
throw new \Exception('This operation can only process single files');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string the next handle in the series A, B, C, ... Z, AA, AB...
|
||||||
|
*/
|
||||||
|
protected function nextHandle()
|
||||||
|
{
|
||||||
|
// N.B. Multi-character handles are only available in pdftk 1.45+
|
||||||
|
|
||||||
|
$i = $this->_handle++;
|
||||||
|
$char = 'A';
|
||||||
|
while ($i-- > 0) {
|
||||||
|
$char++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $char;
|
||||||
|
}
|
||||||
|
}
|
||||||
233
composer/mikehaertl/php-pdftk/src/XfdfFile.php
Normal file
233
composer/mikehaertl/php-pdftk/src/XfdfFile.php
Normal file
|
|
@ -0,0 +1,233 @@
|
||||||
|
<?php
|
||||||
|
namespace mikehaertl\pdftk;
|
||||||
|
|
||||||
|
use mikehaertl\tmp\File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XfdfFile
|
||||||
|
*
|
||||||
|
* This class represents a temporary XFDF file that can be used to fill a PDF
|
||||||
|
* form with valid unicode characters.
|
||||||
|
*
|
||||||
|
* Form data must be passed to the constructor as an array in this form:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* [
|
||||||
|
* // Field name => field value
|
||||||
|
* 'Firstname' => 'John',
|
||||||
|
*
|
||||||
|
* // Hierarchical/nested fields in dot notation
|
||||||
|
* 'Address.Street' => 'Some Street',
|
||||||
|
* 'Address.City' => 'Any City',
|
||||||
|
*
|
||||||
|
* // Multi value fields
|
||||||
|
* 'Pets' => ['Cat', 'Mouse'],
|
||||||
|
* ]
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will result in the following XML structure (header/footer omitted):
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <field name="Firstname">
|
||||||
|
* <Value>John</Value>
|
||||||
|
* </field>
|
||||||
|
* <field name="Address">
|
||||||
|
* <field name="Street">
|
||||||
|
* <Value>Some Street</Value>
|
||||||
|
* </field>
|
||||||
|
* <field name="City">
|
||||||
|
* <Value>Any City</Value>
|
||||||
|
* </field>
|
||||||
|
* </field>
|
||||||
|
* <field name="Pets">
|
||||||
|
* <Value>Cat</Value>
|
||||||
|
* <Value>Mouse</Value>
|
||||||
|
* </field>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @author Tomas Holy <holy@interconnect.cz>
|
||||||
|
* @author Michael Härtl <haertl.mike@gmail.com>
|
||||||
|
* @license http://www.opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
class XfdfFile extends File
|
||||||
|
{
|
||||||
|
// XFDF file header
|
||||||
|
const XFDF_HEADER = <<<FDF
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
|
||||||
|
<fields>
|
||||||
|
|
||||||
|
FDF;
|
||||||
|
|
||||||
|
// XFDF file footer
|
||||||
|
const XFDF_FOOTER = <<<FDF
|
||||||
|
</fields>
|
||||||
|
</xfdf>
|
||||||
|
|
||||||
|
FDF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param array $data the form data as name => value
|
||||||
|
* @param string|null $suffix the optional suffix for the tmp file
|
||||||
|
* @param string|null $prefix the optional prefix for the tmp file. If null
|
||||||
|
* 'php_tmpfile_' is used.
|
||||||
|
* @param string|null $directory directory where the file should be
|
||||||
|
* created. Autodetected if not provided.
|
||||||
|
* @param string|null $encoding of the data. Default is 'UTF-8'.
|
||||||
|
*/
|
||||||
|
public function __construct($data, $suffix = null, $prefix = null, $directory = null, $encoding = 'UTF-8')
|
||||||
|
{
|
||||||
|
if ($directory === null) {
|
||||||
|
$directory = self::getTempDir();
|
||||||
|
}
|
||||||
|
if ($suffix === null) {
|
||||||
|
$suffix = '.xfdf';
|
||||||
|
}
|
||||||
|
if ($prefix === null) {
|
||||||
|
$prefix = 'php_pdftk_xfdf_';
|
||||||
|
}
|
||||||
|
|
||||||
|
$tempfile = tempnam($directory, $prefix);
|
||||||
|
$this->_fileName = $tempfile . $suffix;
|
||||||
|
rename($tempfile, $this->_fileName);
|
||||||
|
|
||||||
|
$fields = $this->parseData($data, $encoding);
|
||||||
|
$this->writeXml($fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses an array of key/value data into a nested array structure.
|
||||||
|
*
|
||||||
|
* The data may use keys in dot notation (#55). Values can also be arrays in
|
||||||
|
* case of multi value fields (#148). To make both distinguishable in the
|
||||||
|
* result array keys that represent field names are prefixed with `_`. This
|
||||||
|
* also allows for numeric field names (#260).
|
||||||
|
*
|
||||||
|
* For example an array like this:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* [
|
||||||
|
* 'a' => 'value a',
|
||||||
|
* 'b.x' => 'value b.x',
|
||||||
|
* 'b.y' => 'value b.y',
|
||||||
|
*
|
||||||
|
* 'c.0' => 'val c.0',
|
||||||
|
* 'c.1' => 'val c.1',
|
||||||
|
*
|
||||||
|
* 'd' => ['m1', 'm2'],
|
||||||
|
* ]
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Will become:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* [
|
||||||
|
* '_a' => 'value a',
|
||||||
|
* '_b' => [
|
||||||
|
* '_x' => 'value b.x',
|
||||||
|
* '_y' => 'value b.y',
|
||||||
|
* ],
|
||||||
|
* '_c' => [
|
||||||
|
* '_0' => 'value c.0',
|
||||||
|
* '_1' => 'value c.1',
|
||||||
|
* ],
|
||||||
|
* '_d' => [
|
||||||
|
* // notice the missing underscore in the keys
|
||||||
|
* 0 => 'm1',
|
||||||
|
* 1 => 'm2',
|
||||||
|
* ],
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param mixed $data the data to parse
|
||||||
|
* @param string the encoding of the data
|
||||||
|
* @return array the result array in UTF-8 encoding with dot keys converted
|
||||||
|
* to nested arrays
|
||||||
|
*/
|
||||||
|
protected function parseData($data, $encoding)
|
||||||
|
{
|
||||||
|
$result = array();
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
if ($encoding !== 'UTF-8' && function_exists('mb_convert_encoding')) {
|
||||||
|
$key = mb_convert_encoding($key, 'UTF-8', $encoding);
|
||||||
|
$value = mb_convert_encoding($value, 'UTF-8', $encoding);
|
||||||
|
}
|
||||||
|
if (strpos($key, '.') === false) {
|
||||||
|
$result['_' . $key] = $value;
|
||||||
|
} else {
|
||||||
|
$target = &$result;
|
||||||
|
$keyParts = explode('.', $key);
|
||||||
|
$lastPart = array_pop($keyParts);
|
||||||
|
foreach ($keyParts as $part) {
|
||||||
|
if (!isset($target['_' . $part])) {
|
||||||
|
$target['_' . $part] = array();
|
||||||
|
}
|
||||||
|
$target = &$target['_' . $part];
|
||||||
|
}
|
||||||
|
$target['_' . $lastPart] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the given fields to an XML file
|
||||||
|
*
|
||||||
|
* @param array $fields the fields in a nested array structure
|
||||||
|
*/
|
||||||
|
protected function writeXml($fields)
|
||||||
|
{
|
||||||
|
// Use fwrite, since file_put_contents() messes around with character encoding
|
||||||
|
$fp = fopen($this->_fileName, 'w');
|
||||||
|
fwrite($fp, self::XFDF_HEADER);
|
||||||
|
$this->writeFields($fp, $fields);
|
||||||
|
fwrite($fp, self::XFDF_FOOTER);
|
||||||
|
fclose($fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the fields to the given filepointer
|
||||||
|
*
|
||||||
|
* @param int $fp
|
||||||
|
* @param mixed[] $fields an array of field values as returned by
|
||||||
|
* `parseData()`.
|
||||||
|
*/
|
||||||
|
protected function writeFields($fp, $fields)
|
||||||
|
{
|
||||||
|
foreach ($fields as $key => $value) {
|
||||||
|
$key = $this->xmlEncode(substr($key,1));
|
||||||
|
fwrite($fp, "<field name=\"$key\">\n");
|
||||||
|
if (!is_array($value)) {
|
||||||
|
$value = array($value);
|
||||||
|
}
|
||||||
|
if (array_key_exists(0, $value)) {
|
||||||
|
// Numeric keys: single or multi-value field
|
||||||
|
foreach($value as $val) {
|
||||||
|
$val = $this->xmlEncode($val);
|
||||||
|
fwrite($fp, "<value>$val</value>\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// String keys: nested/hierarchical fields
|
||||||
|
$this->writeFields($fp, $value);
|
||||||
|
}
|
||||||
|
fwrite($fp, "</field>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $value the value to encode
|
||||||
|
* @return string|null the value correctly encoded for use in a XML document
|
||||||
|
*/
|
||||||
|
protected function xmlEncode($value)
|
||||||
|
{
|
||||||
|
if ($value === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return defined('ENT_XML1') ?
|
||||||
|
htmlspecialchars($value, ENT_XML1, 'UTF-8') :
|
||||||
|
htmlspecialchars($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
48
composer/mikehaertl/php-shellcommand/.github/workflows/tests.yml
vendored
Normal file
48
composer/mikehaertl/php-shellcommand/.github/workflows/tests.yml
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
name: Tests
|
||||||
|
on: pull_request
|
||||||
|
jobs:
|
||||||
|
phpunit:
|
||||||
|
name: PHP ${{ matrix.php }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
php:
|
||||||
|
- "5.3"
|
||||||
|
- "5.4"
|
||||||
|
- "5.5"
|
||||||
|
- "5.6"
|
||||||
|
- "7.0"
|
||||||
|
- "7.1"
|
||||||
|
- "7.2"
|
||||||
|
- "7.3"
|
||||||
|
- "7.4"
|
||||||
|
- "8.0"
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php }}
|
||||||
|
tools: composer:v2
|
||||||
|
|
||||||
|
- name: Update composer
|
||||||
|
run: composer self-update
|
||||||
|
|
||||||
|
- name: Get composer cache directory
|
||||||
|
id: composer-cache
|
||||||
|
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||||
|
|
||||||
|
- name: Cache dependencies
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ${{ steps.composer-cache.outputs.dir }}
|
||||||
|
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
|
||||||
|
restore-keys: ${{ runner.os }}-composer-
|
||||||
|
|
||||||
|
- name: Install composer packages
|
||||||
|
run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
|
||||||
|
|
||||||
|
- name: Run phpunit
|
||||||
|
run: vendor/bin/phpunit --color=always
|
||||||
102
composer/mikehaertl/php-shellcommand/CHANGELOG.md
Normal file
102
composer/mikehaertl/php-shellcommand/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
# CHANGELOG
|
||||||
|
|
||||||
|
## 1.6.4
|
||||||
|
|
||||||
|
* Let getExecCommand() not cache the created command string
|
||||||
|
|
||||||
|
## 1.6.3
|
||||||
|
|
||||||
|
* Include PHP 5.3 in version requirements
|
||||||
|
|
||||||
|
## 1.6.2
|
||||||
|
|
||||||
|
* Add .gitattributes to reduce package size
|
||||||
|
|
||||||
|
## 1.6.1
|
||||||
|
|
||||||
|
* Issue #44 Fix potential security issue with escaping shell args (@Kirill89 / https://snyk.io/)
|
||||||
|
|
||||||
|
## 1.6.0
|
||||||
|
|
||||||
|
* Issue #24 Implement timeout feature
|
||||||
|
|
||||||
|
## 1.5.0
|
||||||
|
|
||||||
|
* Issue #20 Refactor handling of stdin/stdou/sterr streams with proc_open().
|
||||||
|
By default these streams now operate in non-blocking mode which should fix
|
||||||
|
many hanging issues that were caused when the command received/sent a lot of
|
||||||
|
input/output. This is the new default on Non-Windows systems (it's not
|
||||||
|
supported on Windows, though). To get the old behavior the nonBlockingMode
|
||||||
|
option can be set to false.
|
||||||
|
|
||||||
|
## 1.4.1
|
||||||
|
|
||||||
|
* Allow command names with spaces on Windows (@Robindfuller )
|
||||||
|
|
||||||
|
## 1.4.0
|
||||||
|
|
||||||
|
* Allow stdin to be a stream or a file handle (@Arzaroth)
|
||||||
|
|
||||||
|
## 1.3.0
|
||||||
|
|
||||||
|
* Add setStdIn() which allows to pipe an input string to the command (@martinqvistgard)
|
||||||
|
|
||||||
|
## 1.2.5
|
||||||
|
|
||||||
|
* Issue #22 Fix execution of relative file paths on windows
|
||||||
|
|
||||||
|
## 1.2.4
|
||||||
|
|
||||||
|
* Reverted changes for Issue #20 as this introduced BC breaking problems
|
||||||
|
|
||||||
|
## 1.2.3
|
||||||
|
|
||||||
|
* Issue #20: Read stderr before stdout to avoid hanging processes
|
||||||
|
|
||||||
|
## 1.2.2
|
||||||
|
|
||||||
|
* Issue #16: Command on different drive didn't work on windows
|
||||||
|
|
||||||
|
## 1.2.1
|
||||||
|
|
||||||
|
* Issue #1: Command with spaces didn't work on windows
|
||||||
|
|
||||||
|
## 1.2.0
|
||||||
|
|
||||||
|
* Add option to return untrimmed output and error
|
||||||
|
|
||||||
|
## 1.1.0
|
||||||
|
|
||||||
|
* Issue #7: UTF-8 encoded arguments where truncated
|
||||||
|
|
||||||
|
## 1.0.7
|
||||||
|
|
||||||
|
* Issue #6: Solve `proc_open()` pipe configuration for both, Windows / Linux
|
||||||
|
|
||||||
|
## 1.0.6
|
||||||
|
|
||||||
|
* Undid `proc_open()` changes as it broke error capturing
|
||||||
|
|
||||||
|
## 1.0.5
|
||||||
|
|
||||||
|
* Improve `proc_open()` pipe configuration
|
||||||
|
|
||||||
|
## 1.0.4
|
||||||
|
|
||||||
|
* Add `$useExec` option to fix Windows issues (#3)
|
||||||
|
|
||||||
|
## 1.0.3
|
||||||
|
|
||||||
|
* Add `getExecuted()` to find out execution status of the command
|
||||||
|
|
||||||
|
## 1.0.2
|
||||||
|
|
||||||
|
* Add `$escape` parameter to `addArg()` to override escaping settings per call
|
||||||
|
|
||||||
|
## 1.0.1
|
||||||
|
|
||||||
|
* Minor fixes
|
||||||
|
|
||||||
|
## 1.0.0
|
||||||
|
|
||||||
|
* Initial release
|
||||||
21
composer/mikehaertl/php-shellcommand/LICENSE
Normal file
21
composer/mikehaertl/php-shellcommand/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Michael Härtl
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
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.
|
||||||
204
composer/mikehaertl/php-shellcommand/README.md
Normal file
204
composer/mikehaertl/php-shellcommand/README.md
Normal file
|
|
@ -0,0 +1,204 @@
|
||||||
|
php-shellcommand
|
||||||
|
================
|
||||||
|
|
||||||
|
[](https://github.com/mikehaertl/php-shellcommand/actions)
|
||||||
|
[](https://packagist.org/packages/mikehaertl/php-shellcommand)
|
||||||
|
[](https://packagist.org/packages/mikehaertl/php-shellcommand)
|
||||||
|
[](https://github.com/mikehaertl/php-shellcommand/blob/master/LICENSE)
|
||||||
|
[](https://packagist.org/packages/mikehaertl/php-shellcommand)
|
||||||
|
|
||||||
|
php-shellcommand provides a simple object oriented interface to execute shell commands.
|
||||||
|
|
||||||
|
## Installing
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
Your php version must be `5.4` or later.
|
||||||
|
|
||||||
|
### Installing with composer
|
||||||
|
|
||||||
|
This package can be installed easily using composer.
|
||||||
|
|
||||||
|
```
|
||||||
|
composer require mikehaertl/php-shellcommand
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* Catches `stdOut`, `stdErr` and `exitCode`
|
||||||
|
* Handle argument escaping
|
||||||
|
* Pass environment vars and other options to `proc_open()`
|
||||||
|
* Pipe resources like files or streams into the command
|
||||||
|
* Timeout for execution
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Basic Example
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
use mikehaertl\shellcommand\Command;
|
||||||
|
|
||||||
|
// Basic example
|
||||||
|
$command = new Command('/usr/local/bin/mycommand -a -b');
|
||||||
|
if ($command->execute()) {
|
||||||
|
echo $command->getOutput();
|
||||||
|
} else {
|
||||||
|
echo $command->getError();
|
||||||
|
$exitCode = $command->getExitCode();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced Features
|
||||||
|
|
||||||
|
#### Add Arguments
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
$command = new Command('/bin/somecommand');
|
||||||
|
// Add arguments with correct escaping:
|
||||||
|
// results in --name='d'\''Artagnan'
|
||||||
|
$command->addArg('--name=', "d'Artagnan");
|
||||||
|
|
||||||
|
// Add argument with several values
|
||||||
|
// results in --keys key1 key2
|
||||||
|
$command->addArg('--keys', ['key1','key2']);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pipe Input Into Command
|
||||||
|
|
||||||
|
From string:
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
$command = new ('jq'); // jq is a pretty printer
|
||||||
|
$command->setStdIn('{"foo": 0}');
|
||||||
|
if (!$command->execute()) {
|
||||||
|
echo $command->getError();
|
||||||
|
} else {
|
||||||
|
echo $command->getOutput();
|
||||||
|
}
|
||||||
|
// Output:
|
||||||
|
// {
|
||||||
|
// "foo": 0
|
||||||
|
// }
|
||||||
|
```
|
||||||
|
|
||||||
|
From file:
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
$fh = fopen('test.json', 'r');
|
||||||
|
// error checks left out...
|
||||||
|
$command = new Command('jq');
|
||||||
|
$command->setStdIn($fh);
|
||||||
|
if (!$command->execute()) {
|
||||||
|
echo $command->getError();
|
||||||
|
} else {
|
||||||
|
echo $command->getOutput();
|
||||||
|
}
|
||||||
|
fclose($fh);
|
||||||
|
```
|
||||||
|
From URL:
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
$fh = fopen('https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41&hourly=temperature_2m,relativehumidity_2m,windspeed_10m', 'r');
|
||||||
|
// error checks left out...
|
||||||
|
$command = new Command('jq');
|
||||||
|
$command->setStdIn($fh);
|
||||||
|
if (!$command->execute()) {
|
||||||
|
echo $command->getError();
|
||||||
|
} else {
|
||||||
|
echo $command->getOutput();
|
||||||
|
}
|
||||||
|
fclose($fh);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Set Command Instance Options
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
// Create command with options array
|
||||||
|
$command = new Command([
|
||||||
|
'command' => '/usr/local/bin/mycommand',
|
||||||
|
|
||||||
|
// Will be passed as environment variables to the command
|
||||||
|
'procEnv' => [
|
||||||
|
'DEMOVAR' => 'demovalue'
|
||||||
|
],
|
||||||
|
|
||||||
|
// Will be passed as options to proc_open()
|
||||||
|
'procOptions' => [
|
||||||
|
'bypass_shell' => true,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Properties
|
||||||
|
|
||||||
|
* `$escapeArgs`: Whether to escape any argument passed through `addArg()`. Default is `true`.
|
||||||
|
* `$escapeCommand`: Whether to escape the command passed to `setCommand()` or the constructor.
|
||||||
|
This is only useful if `$escapeArgs` is `false`. Default is `false`.
|
||||||
|
* `$useExec`: Whether to use `exec()` instead of `proc_open()`. This is a workaround for OS which
|
||||||
|
have problems with `proc_open()`. Default is `false`.
|
||||||
|
* `$captureStdErr`: Whether to capture stderr when `useExec` is set. This will try to redirect
|
||||||
|
the otherwhise unavailable `stderr` to `stdout`, so that both have the same content on error.
|
||||||
|
Default is `true`.
|
||||||
|
* `$procCwd`: The initial working dir passed to `proc_open()`. Default is `null` for current
|
||||||
|
PHP working dir.
|
||||||
|
* `$procEnv`: An array with environment variables to pass to `proc_open()`. Default is `null` for none.
|
||||||
|
* `$procOptions`: An array of `other_options` for `proc_open()`. Default is `null` for none.
|
||||||
|
* `$nonBlockingMode`: Whether to set the stdin/stdout/stderr streams to non-blocking
|
||||||
|
mode when `proc_open()` is used. This allows to have huge inputs/outputs
|
||||||
|
without making the process hang. The default is `null` which will enable
|
||||||
|
the feature on Non-Windows systems. Set it to `true` or `false` to manually
|
||||||
|
enable/disable it. Note that it doesn't work on Windows.
|
||||||
|
* `$timeout`: The time in seconds after which the command should be
|
||||||
|
terminated. This only works in non-blocking mode. Default is `null` which
|
||||||
|
means the process is never terminated.
|
||||||
|
* `$locale`: The locale to (temporarily) set with `setlocale()` before running the command.
|
||||||
|
This can be set to e.g. `en_US.UTF-8` if you have issues with UTF-8 encoded arguments.
|
||||||
|
|
||||||
|
You can configure all these properties via an array that you pass in the constructor. You can also
|
||||||
|
pass `command`, `execCommand` and `args` as options. This will call the respective setter (`setCommand()`,
|
||||||
|
`setExecCommand()`, etc.).
|
||||||
|
|
||||||
|
### Methods
|
||||||
|
|
||||||
|
* `__construct($options = null)`
|
||||||
|
* `$options`: either a command string or an options array (see `setOptions()`)
|
||||||
|
* `__toString()`: The result from `getExecCommand()`
|
||||||
|
* `setOptions($options)`: Set command options
|
||||||
|
* `$options`: array of name => value options that should be applied to the object.
|
||||||
|
You can also pass options that use a setter, e.g. you can pass a `command` option which
|
||||||
|
will be passed to `setCommand().`
|
||||||
|
* `setCommand($command)`: Set command
|
||||||
|
* `$command`: The command or full command string to execute, like `gzip` or `gzip -d`.
|
||||||
|
You can still call `addArg()` to add more arguments to the command. If `$escapeCommand` was
|
||||||
|
set to `true`, the command gets escaped through `escapeshellcmd()`.
|
||||||
|
* `getCommand()`: The command that was set through `setCommand()` or passed to the constructor.
|
||||||
|
* `getExecCommand()`: The full command string to execute.
|
||||||
|
* `setArgs($args)`: Set argument as string
|
||||||
|
* `$args`: The command arguments as string. Note, that these will not get escaped. This
|
||||||
|
will overwrite the args added with `addArgs()`.
|
||||||
|
* `getArgs()`: The command arguments that where set through `setArgs()` or `addArg()`, as string
|
||||||
|
* `addArg($key, $value=null, $escape=null)`: Add argument with correct escaping
|
||||||
|
* `$key`: The argument key to add e.g. `--feature` or `--name=`. If the key does not end with
|
||||||
|
and `=`, the (optional) `$value` will be separated by a space. The key will get
|
||||||
|
escaped if `$escapeArgs` is `true`.
|
||||||
|
* `$value`: The optional argument value which will get escaped if `$escapeArgs` is `true`.
|
||||||
|
An array can be passed to add more than one value for a key, e.g. `addArg('--exclude', ['val1','val2'])`
|
||||||
|
which will create the option "--exclude 'val1' 'val2'".
|
||||||
|
* `$escape`: If set, this overrides the `$escapeArgs` setting and enforces escaping/no escaping
|
||||||
|
* `setStdIn()`: String or resource to supply to command via standard input.
|
||||||
|
This enables the same functionality as piping on the command line. It can
|
||||||
|
also be a resource like a file handle or a stream in which case its content
|
||||||
|
will be piped into the command like an input redirection.
|
||||||
|
* `getOutput()`: The command output as string. Empty if none.
|
||||||
|
* `getError()`: The error message, either stderr or internal message. Empty if no error.
|
||||||
|
* `getStdErr()`: The stderr output. Empty if none.
|
||||||
|
* `getExitCode()`: The exit code or `null` if command was not executed.
|
||||||
|
* `getExecuted()`: Whether the command was successfully executed.
|
||||||
|
* `getIsWindows()`: Whether we are on a Windows Owe are on a Windows OS
|
||||||
|
* `execute()`: Executes the command and returns `true` on success, `false` otherwhise.
|
||||||
|
|
||||||
|
> **Note:** `getError()`, `getStdErr()` and `getOutput()` return the trimmed output.
|
||||||
|
> You can pass `false` to these methods if you need any possible line breaks at the end.
|
||||||
28
composer/mikehaertl/php-shellcommand/composer.json
Normal file
28
composer/mikehaertl/php-shellcommand/composer.json
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"name": "mikehaertl/php-shellcommand",
|
||||||
|
"description": "An object oriented interface to shell commands",
|
||||||
|
"keywords": ["shell"],
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Michael Härtl",
|
||||||
|
"email": "haertl.mike@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": ">= 5.3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": ">4.0 <=9.4"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"mikehaertl\\shellcommand\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"tests\\": "tests"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
568
composer/mikehaertl/php-shellcommand/src/Command.php
Normal file
568
composer/mikehaertl/php-shellcommand/src/Command.php
Normal file
|
|
@ -0,0 +1,568 @@
|
||||||
|
<?php
|
||||||
|
namespace mikehaertl\shellcommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command
|
||||||
|
*
|
||||||
|
* This class represents a shell command.
|
||||||
|
*
|
||||||
|
* Its meant for exuting a single command and capturing stdout and stderr.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* $command = new Command('/usr/local/bin/mycommand -a -b');
|
||||||
|
* $command->addArg('--name=', "d'Artagnan");
|
||||||
|
* if ($command->execute()) {
|
||||||
|
* echo $command->getOutput();
|
||||||
|
* } else {
|
||||||
|
* echo $command->getError();
|
||||||
|
* $exitCode = $command->getExitCode();
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @author Michael Härtl <haertl.mike@gmail.com>
|
||||||
|
* @license http://www.opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
class Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var bool whether to escape any argument passed through `addArg()`.
|
||||||
|
* Default is `true`.
|
||||||
|
*/
|
||||||
|
public $escapeArgs = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool whether to escape the command passed to `setCommand()` or the
|
||||||
|
* constructor. This is only useful if `$escapeArgs` is `false`. Default
|
||||||
|
* is `false`.
|
||||||
|
*/
|
||||||
|
public $escapeCommand = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool whether to use `exec()` instead of `proc_open()`. This can be
|
||||||
|
* used on Windows system to workaround some quirks there. Note, that any
|
||||||
|
* errors from your command will be output directly to the PHP output
|
||||||
|
* stream. `getStdErr()` will also not work anymore and thus you also won't
|
||||||
|
* get the error output from `getError()` in this case. You also can't pass
|
||||||
|
* any environment variables to the command if this is enabled. Default is
|
||||||
|
* `false`.
|
||||||
|
*/
|
||||||
|
public $useExec = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool whether to capture stderr (2>&1) when `useExec` is true. This
|
||||||
|
* will try to redirect the stderr to stdout and provide the complete
|
||||||
|
* output of both in `getStdErr()` and `getError()`. Default is `true`.
|
||||||
|
*/
|
||||||
|
public $captureStdErr = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string|null the initial working dir for `proc_open()`. Default is
|
||||||
|
* `null` for current PHP working dir.
|
||||||
|
*/
|
||||||
|
public $procCwd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array|null an array with environment variables to pass to
|
||||||
|
* `proc_open()`. Default is `null` for none.
|
||||||
|
*/
|
||||||
|
public $procEnv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array|null an array of other_options for `proc_open()`. Default is
|
||||||
|
* `null` for none.
|
||||||
|
*/
|
||||||
|
public $procOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool|null whether to set the stdin/stdout/stderr streams to
|
||||||
|
* non-blocking mode when `proc_open()` is used. This allows to have huge
|
||||||
|
* inputs/outputs without making the process hang. The default is `null`
|
||||||
|
* which will enable the feature on Non-Windows systems. Set it to `true`
|
||||||
|
* or `false` to manually enable/disable it. It does not work on Windows.
|
||||||
|
*/
|
||||||
|
public $nonBlockingMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int the time in seconds after which a command should be terminated.
|
||||||
|
* This only works in non-blocking mode. Default is `null` which means the
|
||||||
|
* process is never terminated.
|
||||||
|
*/
|
||||||
|
public $timeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var null|string the locale to temporarily set before calling
|
||||||
|
* `escapeshellargs()`. Default is `null` for none.
|
||||||
|
*/
|
||||||
|
public $locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var null|string|resource to pipe to standard input
|
||||||
|
*/
|
||||||
|
protected $_stdIn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string the command to execute
|
||||||
|
*/
|
||||||
|
protected $_command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array the list of command arguments
|
||||||
|
*/
|
||||||
|
protected $_args = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string the stdout output
|
||||||
|
*/
|
||||||
|
protected $_stdOut = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string the stderr output
|
||||||
|
*/
|
||||||
|
protected $_stdErr = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int the exit code
|
||||||
|
*/
|
||||||
|
protected $_exitCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string the error message
|
||||||
|
*/
|
||||||
|
protected $_error = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool whether the command was successfully executed
|
||||||
|
*/
|
||||||
|
protected $_executed = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|array $options either a command string or an options array
|
||||||
|
* @see setOptions
|
||||||
|
*/
|
||||||
|
public function __construct($options = null)
|
||||||
|
{
|
||||||
|
if (is_array($options)) {
|
||||||
|
$this->setOptions($options);
|
||||||
|
} elseif (is_string($options)) {
|
||||||
|
$this->setCommand($options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $options array of name => value options (i.e. public
|
||||||
|
* properties) that should be applied to this object. You can also pass
|
||||||
|
* options that use a setter, e.g. you can pass a `fileName` option which
|
||||||
|
* will be passed to `setFileName()`.
|
||||||
|
* @throws \Exception on unknown option keys
|
||||||
|
* @return static for method chaining
|
||||||
|
*/
|
||||||
|
public function setOptions($options)
|
||||||
|
{
|
||||||
|
foreach ($options as $key => $value) {
|
||||||
|
if (property_exists($this, $key)) {
|
||||||
|
$this->$key = $value;
|
||||||
|
} else {
|
||||||
|
$method = 'set'.ucfirst($key);
|
||||||
|
if (method_exists($this, $method)) {
|
||||||
|
call_user_func(array($this,$method), $value);
|
||||||
|
} else {
|
||||||
|
throw new \Exception("Unknown configuration option '$key'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $command the command or full command string to execute,
|
||||||
|
* like 'gzip' or 'gzip -d'. You can still call addArg() to add more
|
||||||
|
* arguments to the command. If `$escapeCommand` was set to true, the command
|
||||||
|
* gets escaped with `escapeshellcmd()`.
|
||||||
|
* @return static for method chaining
|
||||||
|
*/
|
||||||
|
public function setCommand($command)
|
||||||
|
{
|
||||||
|
if ($this->escapeCommand) {
|
||||||
|
$command = escapeshellcmd($command);
|
||||||
|
}
|
||||||
|
if ($this->getIsWindows()) {
|
||||||
|
// Make sure to switch to correct drive like "E:" first if we have
|
||||||
|
// a full path in command
|
||||||
|
if (isset($command[1]) && $command[1] === ':') {
|
||||||
|
$position = 1;
|
||||||
|
// Could be a quoted absolute path because of spaces.
|
||||||
|
// i.e. "C:\Program Files (x86)\file.exe"
|
||||||
|
} elseif (isset($command[2]) && $command[2] === ':') {
|
||||||
|
$position = 2;
|
||||||
|
} else {
|
||||||
|
$position = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Absolute path. If it's a relative path, let it slide.
|
||||||
|
if ($position) {
|
||||||
|
$command = sprintf(
|
||||||
|
$command[$position - 1] . ': && cd %s && %s',
|
||||||
|
escapeshellarg(dirname($command)),
|
||||||
|
escapeshellarg(basename($command))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->_command = $command;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|resource $stdIn If set, the string will be piped to the
|
||||||
|
* command via standard input. This enables the same functionality as
|
||||||
|
* piping on the command line. It can also be a resource like a file
|
||||||
|
* handle or a stream in which case its content will be piped into the
|
||||||
|
* command like an input redirection.
|
||||||
|
* @return static for method chaining
|
||||||
|
*/
|
||||||
|
public function setStdIn($stdIn) {
|
||||||
|
$this->_stdIn = $stdIn;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string|null the command that was set through `setCommand()` or
|
||||||
|
* passed to the constructor. `null` if none.
|
||||||
|
*/
|
||||||
|
public function getCommand()
|
||||||
|
{
|
||||||
|
return $this->_command;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string|bool the full command string to execute. If no command
|
||||||
|
* was set with `setCommand()` or passed to the constructor it will return
|
||||||
|
* `false`.
|
||||||
|
*/
|
||||||
|
public function getExecCommand()
|
||||||
|
{
|
||||||
|
$command = $this->getCommand();
|
||||||
|
if (!$command) {
|
||||||
|
$this->_error = 'Could not locate any executable command';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$args = $this->getArgs();
|
||||||
|
return $args ? $command.' '.$args : $command;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $args the command arguments as string like `'--arg1=value1
|
||||||
|
* --arg2=value2'`. Note that this string will not get escaped. This will
|
||||||
|
* overwrite the args added with `addArgs()`.
|
||||||
|
* @return static for method chaining
|
||||||
|
*/
|
||||||
|
public function setArgs($args)
|
||||||
|
{
|
||||||
|
$this->_args = array($args);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string the command args that where set with `setArgs()` or added
|
||||||
|
* with `addArg()` separated by spaces.
|
||||||
|
*/
|
||||||
|
public function getArgs()
|
||||||
|
{
|
||||||
|
return implode(' ', $this->_args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key the argument key to add e.g. `--feature` or
|
||||||
|
* `--name=`. If the key does not end with `=`, the (optional) $value will
|
||||||
|
* be separated by a space. The key will get escaped if `$escapeArgs` is `true`.
|
||||||
|
* @param string|array|null $value the optional argument value which will
|
||||||
|
* get escaped if $escapeArgs is true. An array can be passed to add more
|
||||||
|
* than one value for a key, e.g.
|
||||||
|
* `addArg('--exclude', array('val1','val2'))`
|
||||||
|
* which will create the option
|
||||||
|
* `'--exclude' 'val1' 'val2'`.
|
||||||
|
* @param bool|null $escape if set, this overrides the `$escapeArgs` setting
|
||||||
|
* and enforces escaping/no escaping of keys and values
|
||||||
|
* @return static for method chaining
|
||||||
|
*/
|
||||||
|
public function addArg($key, $value = null, $escape = null)
|
||||||
|
{
|
||||||
|
$doEscape = $escape !== null ? $escape : $this->escapeArgs;
|
||||||
|
$useLocale = $doEscape && $this->locale !== null;
|
||||||
|
|
||||||
|
if ($useLocale) {
|
||||||
|
$locale = setlocale(LC_CTYPE, 0); // Returns current locale setting
|
||||||
|
setlocale(LC_CTYPE, $this->locale);
|
||||||
|
}
|
||||||
|
if ($value === null) {
|
||||||
|
$this->_args[] = $doEscape ? escapeshellarg($key) : $key;
|
||||||
|
} else {
|
||||||
|
if (substr($key, -1) === '=') {
|
||||||
|
$separator = '=';
|
||||||
|
$argKey = substr($key, 0, -1);
|
||||||
|
} else {
|
||||||
|
$separator = ' ';
|
||||||
|
$argKey = $key;
|
||||||
|
}
|
||||||
|
$argKey = $doEscape ? escapeshellarg($argKey) : $argKey;
|
||||||
|
|
||||||
|
if (is_array($value)) {
|
||||||
|
$params = array();
|
||||||
|
foreach ($value as $v) {
|
||||||
|
$params[] = $doEscape ? escapeshellarg($v) : $v;
|
||||||
|
}
|
||||||
|
$this->_args[] = $argKey . $separator . implode(' ', $params);
|
||||||
|
} else {
|
||||||
|
$this->_args[] = $argKey . $separator .
|
||||||
|
($doEscape ? escapeshellarg($value) : $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($useLocale) {
|
||||||
|
setlocale(LC_CTYPE, $locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $trim whether to `trim()` the return value. The default is `true`.
|
||||||
|
* @param string $characters the list of characters to trim. The default
|
||||||
|
* is ` \t\n\r\0\v\f`.
|
||||||
|
* @return string the command output (stdout). Empty if none.
|
||||||
|
*/
|
||||||
|
public function getOutput($trim = true, $characters = " \t\n\r\0\v\f")
|
||||||
|
{
|
||||||
|
return $trim ? trim($this->_stdOut, $characters) : $this->_stdOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $trim whether to `trim()` the return value. The default is `true`.
|
||||||
|
* @param string $characters the list of characters to trim. The default
|
||||||
|
* is ` \t\n\r\0\v\f`.
|
||||||
|
* @return string the error message, either stderr or an internal message.
|
||||||
|
* Empty string if none.
|
||||||
|
*/
|
||||||
|
public function getError($trim = true, $characters = " \t\n\r\0\v\f")
|
||||||
|
{
|
||||||
|
return $trim ? trim($this->_error, $characters) : $this->_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $trim whether to `trim()` the return value. The default is `true`.
|
||||||
|
* @param string $characters the list of characters to trim. The default
|
||||||
|
* is ` \t\n\r\0\v\f`.
|
||||||
|
* @return string the stderr output. Empty if none.
|
||||||
|
*/
|
||||||
|
public function getStdErr($trim = true, $characters = " \t\n\r\0\v\f")
|
||||||
|
{
|
||||||
|
return $trim ? trim($this->_stdErr, $characters) : $this->_stdErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int|null the exit code or null if command was not executed yet
|
||||||
|
*/
|
||||||
|
public function getExitCode()
|
||||||
|
{
|
||||||
|
return $this->_exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string whether the command was successfully executed
|
||||||
|
*/
|
||||||
|
public function getExecuted()
|
||||||
|
{
|
||||||
|
return $this->_executed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the command
|
||||||
|
*
|
||||||
|
* @return bool whether execution was successful. If `false`, error details
|
||||||
|
* can be obtained from `getError()`, `getStdErr()` and `getExitCode()`.
|
||||||
|
*/
|
||||||
|
public function execute()
|
||||||
|
{
|
||||||
|
$command = $this->getExecCommand();
|
||||||
|
|
||||||
|
if (!$command) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->useExec) {
|
||||||
|
$execCommand = $this->captureStdErr ? "$command 2>&1" : $command;
|
||||||
|
exec($execCommand, $output, $this->_exitCode);
|
||||||
|
$this->_stdOut = implode("\n", $output);
|
||||||
|
if ($this->_exitCode !== 0) {
|
||||||
|
$this->_stdErr = $this->_stdOut;
|
||||||
|
$this->_error = empty($this->_stdErr) ? 'Command failed' : $this->_stdErr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$isInputStream = $this->_stdIn !== null &&
|
||||||
|
is_resource($this->_stdIn) &&
|
||||||
|
in_array(get_resource_type($this->_stdIn), array('file', 'stream'));
|
||||||
|
$isInputString = is_string($this->_stdIn);
|
||||||
|
$hasInput = $isInputStream || $isInputString;
|
||||||
|
$hasTimeout = $this->timeout !== null && $this->timeout > 0;
|
||||||
|
|
||||||
|
$descriptors = array(
|
||||||
|
1 => array('pipe','w'),
|
||||||
|
2 => array('pipe', $this->getIsWindows() ? 'a' : 'w'),
|
||||||
|
);
|
||||||
|
if ($hasInput) {
|
||||||
|
$descriptors[0] = array('pipe', 'r');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Issue #20 Set non-blocking mode to fix hanging processes
|
||||||
|
$nonBlocking = $this->nonBlockingMode === null ?
|
||||||
|
!$this->getIsWindows() : $this->nonBlockingMode;
|
||||||
|
|
||||||
|
$startTime = $hasTimeout ? time() : 0;
|
||||||
|
$process = proc_open($command, $descriptors, $pipes, $this->procCwd, $this->procEnv, $this->procOptions);
|
||||||
|
|
||||||
|
if (is_resource($process)) {
|
||||||
|
|
||||||
|
if ($nonBlocking) {
|
||||||
|
stream_set_blocking($pipes[1], false);
|
||||||
|
stream_set_blocking($pipes[2], false);
|
||||||
|
if ($hasInput) {
|
||||||
|
$writtenBytes = 0;
|
||||||
|
$isInputOpen = true;
|
||||||
|
stream_set_blocking($pipes[0], false);
|
||||||
|
if ($isInputStream) {
|
||||||
|
stream_set_blocking($this->_stdIn, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Due to the non-blocking streams we now have to check in
|
||||||
|
// a loop if the process is still running. We also need to
|
||||||
|
// ensure that all the pipes are written/read alternately
|
||||||
|
// until there's nothing left to write/read.
|
||||||
|
$isRunning = true;
|
||||||
|
while ($isRunning) {
|
||||||
|
$status = proc_get_status($process);
|
||||||
|
$isRunning = $status['running'];
|
||||||
|
|
||||||
|
// We first write to stdIn if we have an input. For big
|
||||||
|
// inputs it will only write until the input buffer of
|
||||||
|
// the command is full (the command may now wait that
|
||||||
|
// we read the output buffers - see below). So we may
|
||||||
|
// have to continue writing in another cycle.
|
||||||
|
//
|
||||||
|
// After everything is written it's safe to close the
|
||||||
|
// input pipe.
|
||||||
|
if ($isRunning && $hasInput && $isInputOpen) {
|
||||||
|
if ($isInputStream) {
|
||||||
|
$written = stream_copy_to_stream($this->_stdIn, $pipes[0], 16 * 1024, $writtenBytes);
|
||||||
|
if ($written === false || $written === 0) {
|
||||||
|
$isInputOpen = false;
|
||||||
|
fclose($pipes[0]);
|
||||||
|
} else {
|
||||||
|
$writtenBytes += $written;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($writtenBytes < strlen($this->_stdIn)) {
|
||||||
|
$writtenBytes += fwrite($pipes[0], substr($this->_stdIn, $writtenBytes));
|
||||||
|
} else {
|
||||||
|
$isInputOpen = false;
|
||||||
|
fclose($pipes[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read out the output buffers because if they are full
|
||||||
|
// the command may block execution. We do this even if
|
||||||
|
// $isRunning is `false`, because there could be output
|
||||||
|
// left in the buffers.
|
||||||
|
//
|
||||||
|
// The latter is only an assumption and needs to be
|
||||||
|
// verified - but it does not hurt either and works as
|
||||||
|
// expected.
|
||||||
|
//
|
||||||
|
while (($out = fgets($pipes[1])) !== false) {
|
||||||
|
$this->_stdOut .= $out;
|
||||||
|
}
|
||||||
|
while (($err = fgets($pipes[2])) !== false) {
|
||||||
|
$this->_stdErr .= $err;
|
||||||
|
}
|
||||||
|
|
||||||
|
$runTime = $hasTimeout ? time() - $startTime : 0;
|
||||||
|
if ($isRunning && $hasTimeout && $runTime >= $this->timeout) {
|
||||||
|
// Only send a SIGTERM and handle status in the next cycle
|
||||||
|
proc_terminate($process);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$isRunning) {
|
||||||
|
$this->_exitCode = $status['exitcode'];
|
||||||
|
if ($this->_exitCode !== 0 && empty($this->_stdErr)) {
|
||||||
|
if ($status['stopped']) {
|
||||||
|
$signal = $status['stopsig'];
|
||||||
|
$this->_stdErr = "Command stopped by signal $signal";
|
||||||
|
} elseif ($status['signaled']) {
|
||||||
|
$signal = $status['termsig'];
|
||||||
|
$this->_stdErr = "Command terminated by signal $signal";
|
||||||
|
} else {
|
||||||
|
$this->_stdErr = 'Command unexpectedly terminated without error message';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose($pipes[1]);
|
||||||
|
fclose($pipes[2]);
|
||||||
|
proc_close($process);
|
||||||
|
} else {
|
||||||
|
// The command is still running. Let's wait some
|
||||||
|
// time before we start the next cycle.
|
||||||
|
usleep(10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($hasInput) {
|
||||||
|
if ($isInputStream) {
|
||||||
|
stream_copy_to_stream($this->_stdIn, $pipes[0]);
|
||||||
|
} elseif ($isInputString) {
|
||||||
|
fwrite($pipes[0], $this->_stdIn);
|
||||||
|
}
|
||||||
|
fclose($pipes[0]);
|
||||||
|
}
|
||||||
|
$this->_stdOut = stream_get_contents($pipes[1]);
|
||||||
|
$this->_stdErr = stream_get_contents($pipes[2]);
|
||||||
|
fclose($pipes[1]);
|
||||||
|
fclose($pipes[2]);
|
||||||
|
$this->_exitCode = proc_close($process);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->_exitCode !== 0) {
|
||||||
|
$this->_error = $this->_stdErr ?
|
||||||
|
$this->_stdErr :
|
||||||
|
"Failed without error message: $command (Exit code: {$this->_exitCode})";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->_error = "Could not run command $command";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_executed = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool whether we are on a Windows OS
|
||||||
|
*/
|
||||||
|
public function getIsWindows()
|
||||||
|
{
|
||||||
|
return strncasecmp(PHP_OS, 'WIN', 3)===0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string the current command string to execute
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return (string) $this->getExecCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
48
composer/mikehaertl/php-tmpfile/.github/workflows/tests.yml
vendored
Normal file
48
composer/mikehaertl/php-tmpfile/.github/workflows/tests.yml
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
name: Tests
|
||||||
|
on: pull_request
|
||||||
|
jobs:
|
||||||
|
phpunit:
|
||||||
|
name: PHP ${{ matrix.php }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
php:
|
||||||
|
- "5.3"
|
||||||
|
- "5.4"
|
||||||
|
- "5.5"
|
||||||
|
- "5.6"
|
||||||
|
- "7.0"
|
||||||
|
- "7.1"
|
||||||
|
- "7.2"
|
||||||
|
- "7.3"
|
||||||
|
- "7.4"
|
||||||
|
- "8.0"
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php }}
|
||||||
|
tools: composer:v2
|
||||||
|
|
||||||
|
- name: Update composer
|
||||||
|
run: composer self-update
|
||||||
|
|
||||||
|
- name: Get composer cache directory
|
||||||
|
id: composer-cache
|
||||||
|
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||||
|
|
||||||
|
- name: Cache dependencies
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ${{ steps.composer-cache.outputs.dir }}
|
||||||
|
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
|
||||||
|
restore-keys: ${{ runner.os }}-composer-
|
||||||
|
|
||||||
|
- name: Install composer packages
|
||||||
|
run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
|
||||||
|
|
||||||
|
- name: Run phpunit
|
||||||
|
run: vendor/bin/phpunit --color=always
|
||||||
21
composer/mikehaertl/php-tmpfile/LICENSE
Normal file
21
composer/mikehaertl/php-tmpfile/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Michael Härtl
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
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.
|
||||||
64
composer/mikehaertl/php-tmpfile/README.md
Normal file
64
composer/mikehaertl/php-tmpfile/README.md
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
php-tmpfile
|
||||||
|
===========
|
||||||
|
|
||||||
|
[](https://github.com/mikehaertl/php-tmpfile/actions)
|
||||||
|
[](https://packagist.org/packages/mikehaertl/php-tmpfile)
|
||||||
|
[](https://packagist.org/packages/mikehaertl/php-tmpfile)
|
||||||
|
[](https://github.com/mikehaertl/php-tmpfile/blob/master/LICENSE)
|
||||||
|
|
||||||
|
A convenience class for temporary files.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* Create temporary file with arbitrary content
|
||||||
|
* Delete file after use (can be disabled)
|
||||||
|
* Send file to client, either inline or with save dialog, optionally with custom HTTP headers
|
||||||
|
* Save file locally
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
use mikehaertl\tmp\File;
|
||||||
|
|
||||||
|
$file = new File('some content', '.html');
|
||||||
|
|
||||||
|
// send to client for download
|
||||||
|
$file->send('home.html');
|
||||||
|
// ... with custom content type (autodetected otherwhise)
|
||||||
|
$file->send('home.html', 'application/pdf');
|
||||||
|
// ... for inline display (download dialog otherwhise)
|
||||||
|
$file->send('home.html', 'application/pdf', true);
|
||||||
|
// ... with custom headers
|
||||||
|
$file->send('home.html', 'application/pdf', true, [
|
||||||
|
'X-Header' => 'Example',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// save to disk
|
||||||
|
$file->saveAs('/dir/test.html');
|
||||||
|
|
||||||
|
// Access file name and directory
|
||||||
|
echo $file->getFileName();
|
||||||
|
echo $file->getTempDir();
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to keep the temporary file, e.g. for debugging, you can set the `$delete` property to false:
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
use mikehaertl\tmp\File;
|
||||||
|
|
||||||
|
$file = new File('some content', '.html');
|
||||||
|
$file->delete = false;
|
||||||
|
```
|
||||||
|
|
||||||
|
Default HTTP headers can also be added:
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
use mikehaertl\tmp\File;
|
||||||
|
|
||||||
|
File::$defaultHeader['X-Header'] = 'My Default';
|
||||||
|
|
||||||
|
$file = new File('some content', '.html');
|
||||||
|
$file->send('home.html');
|
||||||
|
```
|
||||||
26
composer/mikehaertl/php-tmpfile/composer.json
Normal file
26
composer/mikehaertl/php-tmpfile/composer.json
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"name": "mikehaertl/php-tmpfile",
|
||||||
|
"description": "A convenience class for temporary files",
|
||||||
|
"keywords": ["files"],
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Michael Härtl",
|
||||||
|
"email": "haertl.mike@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require-dev": {
|
||||||
|
"php": ">=5.3.0",
|
||||||
|
"phpunit/phpunit": ">4.0 <=9.4"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"mikehaertl\\tmp\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"tests\\": "tests"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
197
composer/mikehaertl/php-tmpfile/src/File.php
Normal file
197
composer/mikehaertl/php-tmpfile/src/File.php
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
<?php
|
||||||
|
namespace mikehaertl\tmp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File
|
||||||
|
*
|
||||||
|
* A convenience class for temporary files.
|
||||||
|
*
|
||||||
|
* @author Michael Härtl <haertl.mike@gmail.com>
|
||||||
|
* @license http://www.opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
class File
|
||||||
|
{
|
||||||
|
const DEFAULT_CONTENT_TYPE = 'application/octet-stream';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool whether to delete the tmp file when it's no longer referenced
|
||||||
|
* or when the request ends. Default is `true`.
|
||||||
|
*/
|
||||||
|
public $delete = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array the list of static default headers to send when `send()` is
|
||||||
|
* called as key/value pairs.
|
||||||
|
*/
|
||||||
|
public static $defaultHeaders = array(
|
||||||
|
'Pragma' => 'public',
|
||||||
|
'Expires' => 0,
|
||||||
|
'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
|
||||||
|
'Content-Transfer-Encoding' => 'binary',
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string the name of this file
|
||||||
|
*/
|
||||||
|
protected $_fileName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string $content the tmp file content
|
||||||
|
* @param string|null $suffix the optional suffix for the tmp file
|
||||||
|
* @param string|null $prefix the optional prefix for the tmp file. If null
|
||||||
|
* 'php_tmpfile_' is used.
|
||||||
|
* @param string|null $directory directory where the file should be
|
||||||
|
* created. Autodetected if not provided.
|
||||||
|
*/
|
||||||
|
public function __construct($content, $suffix = null, $prefix = null, $directory = null)
|
||||||
|
{
|
||||||
|
if ($directory === null) {
|
||||||
|
$directory = self::getTempDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($prefix === null) {
|
||||||
|
$prefix = 'php_tmpfile_';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_fileName = tempnam($directory,$prefix);
|
||||||
|
if ($suffix !== null) {
|
||||||
|
$newName = $this->_fileName . $suffix;
|
||||||
|
rename($this->_fileName, $newName);
|
||||||
|
$this->_fileName = $newName;
|
||||||
|
}
|
||||||
|
file_put_contents($this->_fileName, $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete tmp file on shutdown if `$delete` is `true`
|
||||||
|
*/
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
if ($this->delete && file_exists($this->_fileName)) {
|
||||||
|
unlink($this->_fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send tmp file to client, either inline or as download
|
||||||
|
*
|
||||||
|
* @param string|null $filename the filename to send. If empty, the file is
|
||||||
|
* streamed inline.
|
||||||
|
* @param string|null $contentType the Content-Type header to send. If
|
||||||
|
* `null` the type is auto-detected and if that fails
|
||||||
|
* 'application/octet-stream' is used.
|
||||||
|
* @param bool $inline whether to force inline display of the file, even if
|
||||||
|
* filename is present.
|
||||||
|
* @param array $headers a list of additional HTTP headers to send in the
|
||||||
|
* response as an array. The array keys are the header names like
|
||||||
|
* 'Cache-Control' and the array values the header value strings to send.
|
||||||
|
* Each array value can also be another array of strings if the same header
|
||||||
|
* should be sent multiple times. This can also be used to override
|
||||||
|
* automatically created headers like 'Expires' or 'Content-Length'. To suppress
|
||||||
|
* automatically created headers, `false` can also be used as header value.
|
||||||
|
*/
|
||||||
|
public function send($filename = null, $contentType = null, $inline = false, $headers = array())
|
||||||
|
{
|
||||||
|
$headers = array_merge(self::$defaultHeaders, $headers);
|
||||||
|
|
||||||
|
if ($contentType !== null) {
|
||||||
|
$headers['Content-Type'] = $contentType;
|
||||||
|
} elseif (!isset($headers['Content-Type'])) {
|
||||||
|
$contentType = @mime_content_type($this->_filename);
|
||||||
|
if ($contentType === false) {
|
||||||
|
$contentType = self::DEFAULT_CONTENT_TYPE;
|
||||||
|
}
|
||||||
|
$headers['Content-Type'] = $contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($headers['Content-Length'])) {
|
||||||
|
// #11 Undefined index: HTTP_USER_AGENT
|
||||||
|
$userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
|
||||||
|
|
||||||
|
// #84: Content-Length leads to "network connection was lost" on iOS
|
||||||
|
$isIOS = preg_match('/i(phone|pad|pod)/i', $userAgent);
|
||||||
|
if (!$isIOS) {
|
||||||
|
$headers['Content-Length'] = filesize($this->_fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($filename !== null || $inline) && !isset($headers['Content-Disposition'])) {
|
||||||
|
$disposition = $inline ? 'inline' : 'attachment';
|
||||||
|
$encodedFilename = rawurlencode($filename);
|
||||||
|
$headers['Content-Disposition'] = "$disposition; " .
|
||||||
|
"filename=\"$filename\"; " .
|
||||||
|
"filename*=UTF-8''$encodedFilename";
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->sendHeaders($headers);
|
||||||
|
readfile($this->_fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name the name to save the file as
|
||||||
|
* @return bool whether the file could be saved
|
||||||
|
*/
|
||||||
|
public function saveAs($name)
|
||||||
|
{
|
||||||
|
return copy($this->_fileName, $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string the full file name
|
||||||
|
*/
|
||||||
|
public function getFileName()
|
||||||
|
{
|
||||||
|
return $this->_fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string the path to the temp directory
|
||||||
|
*/
|
||||||
|
public static function getTempDir()
|
||||||
|
{
|
||||||
|
if (function_exists('sys_get_temp_dir')) {
|
||||||
|
return sys_get_temp_dir();
|
||||||
|
} elseif (
|
||||||
|
($tmp = getenv('TMP')) ||
|
||||||
|
($tmp = getenv('TEMP')) ||
|
||||||
|
($tmp = getenv('TMPDIR'))
|
||||||
|
) {
|
||||||
|
return realpath($tmp);
|
||||||
|
} else {
|
||||||
|
return '/tmp';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string the full file name
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->_fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the given list of headers
|
||||||
|
*
|
||||||
|
* @param array $headers the list of headers to send as key/value pairs.
|
||||||
|
* Value can either be a string or an array of strings to send the same
|
||||||
|
* header multiple times.
|
||||||
|
*/
|
||||||
|
protected function sendHeaders($headers)
|
||||||
|
{
|
||||||
|
foreach ($headers as $name => $value) {
|
||||||
|
if ($value === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (is_array($value)) {
|
||||||
|
foreach ($value as $v) {
|
||||||
|
header("$name: $v");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
header("$name: $value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue